﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CdcSoftware.Pivotal.Engine.UI.Forms;
using CdcSoftware.Pivotal.Applications.Core.Common;
using CdcSoftware.Pivotal.Applications.Core.Client;
using CdcSoftware.Pivotal.Engine.UI.DataTypes.Navigation;
using System.Data;
using System.Windows.Forms;
using CdcSoftware.Pivotal.Engine;
using CdcSoftware.Pivotal.Engine.Client.Services.Interfaces;
using CdcSoftware.Pivotal.Engine.DataServices;
using System.Runtime.InteropServices;
using System.Drawing;
using CdcSoftware.Pivotal.Engine.Types.ServerTasks;
using System.Runtime.Serialization.Formatters.Binary;

namespace Pcm.Retail.Client.FormTasks
{
    public partial class RESales: FormClientTask
    {
        # region Private fields
        Dictionary<string, bool> Section_Visibility = new Dictionary<string, bool>();
        int previousQuantity, oldQty = 1;
        string previousDiscCondDesc = string.Empty;
        CdcSoftware.Pivotal.Engine.UI.Forms.PivotalTextBox srcReceiptNo = null;
        static CdcSoftware.Pivotal.WindowsFormControls.DropDownColumn exchangeSecCell = null;
        static CdcSoftware.Pivotal.WindowsFormControls.TextBoxColumn refundSecCell = null;
        bool isQuantityPositive = false;
        static int? bDayQuota;
        bool popupShown = false;
        bool scannedPromotionProduct = false;
        //NN 19082013: Added a memory variable to store the Total Promotion items count which are supposed to be added.
        //This variable will be compared with the Actual Promotions added, and if the count dont match then prompt error message.
        int promotionsCount = 0;
        #endregion

        #region Constructor
        /// <summary>
        /// Default constructor where secondary fields are being initialized to be used across assembly
        /// </summary>
        public RESales()
        {
            //Resetting this varaible as 0 for New Sale.
            promotionsCount = 0;
        }
        #endregion

        #region Public methods
        /// <summary>
        /// Save a new record into database
        /// </summary>
        /// <history>
        /// #Revision   Date        Author  Description
        /// 6.0.12.0    28/01/2013  DS      Initial Version
        /// </history>
        public virtual bool AddRecord()
        { 
            bool saveRecord = false;
            try
            {
                //DS: 27062013 - Now the receipt number generation happens on the Server side only.
                //Call Receipt Generate code to generate the receipt only if staff is logged in.
                //AutoGenerateReceiptNum();

                //NN 16082013: Getting the count of Actual Promotion Items added.

                DataTable orderProduct = this.FormData.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];

                int productWithTypePromotion = (from DataRow myRow in orderProduct.Rows
                                                where TypeConvert.ToString(myRow["RE_Product_Type"]) == "Promotion"
                                                select Id.Create(myRow["RE_Promotion_Id"])).Count();

                //NN 16082013: Comparing the promotionsCount(Promotions items which are supposed to be added) with productWithTypePromotion(Actual Promotion items added).
                //If both the count dont match then raise an error prompt.
                if (promotionsCount != productWithTypePromotion)
                {
                    PivotalMessageBox.Show("There was some error while configuring Promotions." + Environment.NewLine +
                                            "Please create a new Sale.", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    return false;
                }

                saveRecord = base.SaveRecord();
            }
            catch (Exception exc)
            {
                if (exc.Message.Contains("The field 'RE Staff Code' in the segment 'SFA_Order__Product_SFA_Order_I' is a required field.  Please enter a valid value."))
                {
                    PivotalMessageBox.Show("Unable to save the form data. Provide a value for all required fields.", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return false;
                }
                else
                    Globals.HandleException(exc, true);
            }
            return saveRecord;
        }

        /// <summary>
        /// This function deletes the current Form
        /// </summary>
        /// <history>
        /// Revision# Date Author Description
        /// </history>
        public override bool DeleteRecord()
        {
            bool deleteRecord = false;
            try
            {
                deleteRecord = base.DeleteRecord();
            }
            catch (Exception ex)
            {
                Globals.HandleException(ex, true);
            }
            return deleteRecord;
        }

        /// <summary>
        /// This function opens an existing form
        /// </summary>
        /// <history>
        /// Revision# Date Author Description
        /// </history>
        public override bool LoadRecord()
        {
            return base.LoadRecord();
        }

        /// <summary>
        /// This method gets called when the form meta data and data have both been loaded,
        /// and the form UI has finished drawing. Override this method to perform custom
        /// form initialization.
        /// </summary>
        /// <history>
        /// #Revision   Date        Author  Description
        /// 6.0.12.0    31/01/2013  DS      Initial Version
        /// </history>
        public override void OnFormInitialized()
        {
            try
            {
                //DS:When coming from Cashier Login to Sales screen, 
                //focus does not get set. Workaround, open a modal from Cashier Login screen. Chekc here if it is modal, then close and reopen the same form.
                //DS: 18042013 - When opening record from Purchase History
                Id record = this.RecordId;
                if (this.FormView.IsModal())
                {
                    this.FormView.CloseForm(true);
                    Globals.ShowForm("RE_Sale – Walk In", record);
                    return;
                }
                base.OnFormInitialized();
                if (this.TaskPad != null)
                {
                    // Set Visible = false;
                    this.TaskPad.Visible = false;
                    // Or remove the TaskPad
                    this.TaskPad.SuspendNotifications();

                    foreach (TaskPadGroup taskPadGroup in this.TaskPad.TaskPadGroups)
                    {
                        taskPadGroup.Items.Clear();
                    }

                    this.TaskPad.TaskPadGroups.Clear();
                    this.TaskPad.ResumeNotifications();
                }

                //DS: 18042013 - If the inventory check fails for any of the item in the order, then inform the user and delete the sale.
                if (this.RecordId != null)
                {
                    if (TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) == "Pending" || TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) == "Hold")
                    {
                        //DS: 19042013 - For Offline if the POS is not master POS, then don't allow to create new Sale.
                        if (SystemClient.SystemInformation.IsMobile && !Globals.IsMasterPOS)
                        {
                            PivotalMessageBox.Show("This feature is not available Offline when POS is not Master POS.", MessageBoxButtons.OK, MessageBoxIcon.Information);
                            this.FormView.CloseForm(true);
                            return;
                        }
                        bool inventoryAvailableAllItems = true;
                        DataTable orderProduct = this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
                        if (orderProduct != null)
                        {
                            foreach (DataRow dr in orderProduct.Rows)
                            {
                                //For Non-Inventoried products, no need to check for the Inventory.
                                //DS: 20052013 - For -ve items this check needs to be skipped as in that case inventory is getting added.
                                if (TypeConvert.ToBoolean(Globals.SqlIndex("Product", "RE_Inventoried", Id.Create(dr["Product_Id"]))) && TypeConvert.ToInt16(dr["Quantity"]) > 0)
                                {
                                    if (!InventoryCheckForProduct(TypeConvert.ToInt16(dr["Quantity"]), dr["Product_Id"]))
                                    {
                                        inventoryAvailableAllItems = false;
                                        break;
                                    }
                                }
                            }
                        }
                        if (!inventoryAvailableAllItems)
                        {
                            PivotalMessageBox.Show("Insufficient inventory for the items in the order." + Environment.NewLine + "The order will now be deleted.",
                                MessageBoxButtons.OK, MessageBoxIcon.Stop);
                            //Delete the sales record and close the form.
                            this.DeleteRecord();
                            this.FormView.CloseForm(true);
                            return;
                        }
                    }
                }
                SharedLoad();                

                //When Cashier is not logged-in then the form is getting closed in SharedLoad
                //In that case the control is not avaiable and used to through error
                if (this.FormControl.GetControlByName("RECustomerId") != null)
                {
                    //DS: Masking the text box so that the POS cashier can't see the IC scanned.
                    ((TextBox)this.FormControl.GetControlByName("RECustomerId").WindowsControl).PasswordChar = '*';
                }
            }
            catch (Exception exc)
            {
                Globals.HandleException(exc);
            }
        }

        /// <summary>
        /// OnFormLoaded event.
        /// </summary>
        public override void OnFormReloaded()
        {
            try
            {
                base.OnFormReloaded();
                SharedLoad();
            }
            catch (Exception exc)
            {
                Globals.HandleException(exc);
            }
        }

        /// <summary>
        /// This function updates the Form
        /// </summary>
        /// <history>
        /// #Revision   Date        Author  Description
        /// 6.0.12.0    28/01/2013  DS      Initial Version
        /// </history>
        public override bool SaveRecord()
        {
            bool saveRecord = false;

            try
            {
                if (this.RecordId == null)
                {
                    string strMessage = string.Empty;

                    if (this.FormView.VerifyRecord(out strMessage) == false || this.FormView.ValidateRequiredFields(out strMessage) == false)
                    {
                        PivotalMessageBox.Show(strMessage, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return false;
                    }

                    saveRecord = this.AddRecord();
                }
                else
                {
                    saveRecord = base.SaveRecord();
                }
            }
            catch (Exception exc)
            {
                if (exc.Message.Contains("SFA_Order__Product_SFA_Order_I"))
                {
                    PivotalMessageBox.Show("Unable to save the form data. Provide a value for all required fields.", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return false;
                }                
                else
                {
                    Globals.HandleException(exc);
                }
            }
            return saveRecord;
        }
        #endregion

        #region Private methods
        /// <summary>
        /// Fetch Product SKU's
        /// </summary>
        /// <param name="productSerialNumber"></param>
        /// 6.0.12.0    28/01/2013  DS      Initial Version
        private bool AddProductToGrid(DataTable product, DataTable productSerialNumber)
        {
            bool added = scannedPromotionProduct = false;
            try
            {
                DataTable orderProducts = this.FormData.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];

                //Verify if this is a scanning for the products added through Promotion.
                if (productSerialNumber != null || product != null)
                {
                    //Scan for the Product in the Grid. If present, then update the RE_Item_Scanned to true and return. Else Continue with the normal addition procedure.
                    if (UpdateItemScannedForPromotion((productSerialNumber != null) ? productSerialNumber : product))
                    {
                        //DS: 12052013 - When the promotion product is scanned, the focus should be set properly.
                        scannedPromotionProduct = true;
                        return false;
                    }
                }

                //Fetch Product Type before adding a new record.
                object productType, productId = null;
                if (productSerialNumber != null)
                {
                    //For serialized items, do not allow addition of an item which is present in the grid with same serial number and same product id.
                    if (orderProducts.AsEnumerable().Count(a => Id.Equals(Id.Create(a["RE_Product_Serial_No_Id"]), Id.Create(productSerialNumber.Rows[0]["RE_Product_Serial_No_Id"]))
                        && Id.Equals(Id.Create(a["Product_Id"]), Id.Create(this.PrimaryDataRow["RE_Product_Id"]))) > 0)
                    {
                        PivotalMessageBox.Show("Item is already added to the grid.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return false;
                    }

                    //Check whether product is available for sale or not.
                    if (!ProductAvailableForSale(TypeConvert.ToBoolean(productSerialNumber.Rows[0]["Available_For_Sale"]),
                        TypeConvert.ToBoolean(productSerialNumber.Rows[0]["Voucher"]), TypeConvert.ToString(productSerialNumber.Rows[0]["Voucher_Status"])))
                        return false;

                    productId = productSerialNumber.Rows[0]["Product_Id"];
                    productType = Globals.ServerSqlIndex("Product", "RE_Product_Type", Id.Create(productId));
                }
                else
                {
                    productId = product.Rows[0]["Product_Id"];
                    productType = product.Rows[0]["RE_Product_Type"];
                }

                if (string.Equals(TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]), "Refund") && !Convert.IsDBNull(this.PrimaryDataRow["RE_Source_Order_Id"]))
                {
                    PivotalMessageBox.Show("Can not add items for a refund case with source receipt.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }                

                if (string.Equals(TypeConvert.ToString(productType), "Miscellaneous Income"))
                {
                    //Miscellaneous Income can not be added explicitly.
                    PivotalMessageBox.Show("Miscellaneous Income can't be added explicitly.", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    return false;
                }

                //NN 20-06-2013: Added code for Apple Care.
                //Apple Care product shpuld not be selected by Product Dropdown or Barcode scan.
                if (string.Equals(TypeConvert.ToString(productType), "Apple Care"))
                {
                    //Miscellaneous Income can not be added explicitly.
                    PivotalMessageBox.Show("Apple care can't be added explicitly.", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    return false;
                }

                string message = string.Empty;
                if (!string.Equals(TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]), "Walk-In") && !this.FormView.ValidateRequiredFields(out message))
                {
                    //Check for mandatories only when there are no records in the secondary.
                    if (orderProducts.Rows.Count == 0)
                    {
                        PivotalMessageBox.Show("Please provide a value for all required fields before adding a Product as this is not a Walk-In sale.", 
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return false;
                    }
                }

                DataTable price = Globals.GetDataTable("RE_SFA Product Price with Product ? and Currency ? and LOB ?",
                    new object[] { this.PrimaryDataRow["RE_Product_Id"], this.PrimaryDataRow["SFA_Currency_Id"], this.PrimaryDataRow["RE_LOB_Id"] }, "Price");

                if (price != null && price.Rows.Count == 1)
                {
                    //Check for the existence of the Sales storage location for the Store.
                    DataTable storageLoc = Globals.GetDataTable("RE Storage Location with Store Id and Type as Sales?",
                        new object[] { this.PrimaryDataRow["RE_Store_Id"] }, "RE_Storage_Location_Id");
                    if (storageLoc != null && storageLoc.Rows.Count == 1)
                    {
                        int quantity = 1;
                        if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Exchange")
                        {
                            if (this.PrimaryDataRow["RE_Source_Order_Id"] != DBNull.Value)
                            {
                                quantity = 1;
                                if (!InventoryCheck(1, false, productId, null))
                                    return false;
                            }
                            else
                            {
                                //Only the first item should be a negative Qty, all the subsequent should be +ve
                                if (orderProducts.Rows.Count == 0)
                                    quantity = -1;
                                else
                                {
                                    quantity = 1;
                                    if (!InventoryCheck(1, false, productId, null))
                                        return false;
                                }
                            }
                        }
                        else if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Refund")
                        {
                            if (this.PrimaryDataRow["RE_Source_Order_Id"] == DBNull.Value)
                                quantity = -1;
                        }
                        else
                        {
                            quantity = 1;
                            if (!InventoryCheck(1, false, productId, null))
                                return false;
                        }

                        //Add a record to the secondary
                        base.NewSecondaryRecord("SFA_Order__Product_SFA_Order_I");
                        DataRow orderProduct = orderProducts.Rows[orderProducts.Rows.Count - 1];
                        //NN 23052013://Added rowIndex varaible to pass it in MemberDiscount function.
                        int rowIndex = orderProducts.Rows.Count - 1;
                        orderProduct["Product_Id"] = this.PrimaryDataRow["RE_Product_Id"];
                        orderProduct["RE_Product_Type"] = productType;
                        orderProduct["RE_Invisible"] = false;
                        orderProduct["RE_Storage_Location_Id"] = storageLoc.Rows[0]["RE_Storage_Location_Id"];
                        orderProduct["RE_From_Source_Order"] = false;
                        orderProduct["Quantity"] = quantity;
                        orderProduct["RE_Item_Scanned"] = true;
                        if (productSerialNumber != null)
                            orderProduct["RE_Product_Serial_No_Id"] = productSerialNumber.Rows[0]["RE_Product_Serial_No_Id"];

                        if (this.PrimaryDataRow["RE_Staff_Code"] != DBNull.Value)
                        {
                            orderProduct["RE_Staff_Code"] = this.PrimaryDataRow["RE_Staff_Code"];
                            orderProduct["RE_Staff_Id"] = this.PrimaryDataRow["RE_Staff_Id"];
                        }

                        orderProduct["Unit_Price"] = TypeConvert.ToDouble(price.Rows[0]["Price"]);

                        //Apply default discount depending upon the customer type and the product.
                        //BR: Exchange scenario - If (Exchange && Source Order No.==null), then discount condition is to be null.
                        if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) != "Exchange" && TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) != "Refund")
                        {
                            if (!ConfigureProductLevelDiscount(productId, orderProduct, orderProducts.Rows.Count - 1))
                            {
                                //Apply Member default discount. If there is no product level discount available, default the discount condition defined 
                                //at the Loyalty program tier of the contact (Member_Discount_Id)
                                if (TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]) == "Member")
                                    MemberDiscount(orderProduct, rowIndex);
                            }
                        }
                        else
                        {
                            //Added additional chck of Qty < 0,so that it will not apply ExchangeDiscountCondition for New Purchase
                            if (this.PrimaryDataRow["RE_Source_Order_Id"] != DBNull.Value && TypeConvert.ToInt32(orderProduct["Quantity"]) < 0)
                            {
                                //This case does not arise here as -ve items can't be added.
                                UpdateExchangeDiscountCondition(Id.Create(this.PrimaryDataRow["RE_Source_Order_Id"]), productId, orderProduct, (orderProducts.Rows.Count - 1));
                            }
                            else
                            {
                                if (!ConfigureProductLevelDiscount(productId, orderProduct, orderProducts.Rows.Count - 1))
                                {
                                    //Apply Member default discount. If there is no product level discount available, default the discount condition defined 
                                    //at the Loyalty program tier of the contact (Member_Discount_Id)
                                    if (TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]) == "Member")
                                        MemberDiscount(orderProduct, rowIndex);
                                }
                            }

                            if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Exchange")
                            {
                                if (TypeConvert.ToInt32(orderProduct["Quantity"]) > 0)
                                {
                                    if (!TypeConvert.ToBoolean(orderProduct["RE_ProductLevelDisc"]) && TypeConvert.ToBoolean(orderProduct["Product_Id__RE_Discount_Applic"]))
                                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", orderProducts.Rows.Count - 1, true);
                                }
                            }
                        }

                        CommonFieldPopulate(orderProduct);
                        TotalsSectionCalculations();
                        added = true;
                        //Set Void = 1 if Order_Status is set to Void
                        if (this.PrimaryDataRow["RE_Order_Status"].ToString() == "Void")
                            orderProduct["RE_Void"] = 1;

                        //Once a product is added to the secondary do not allow the user to update the Customer_Type and other fields
                        //if (TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]) != "Walk-In")
                        Globals.EnableDisablePrimaryFields(false, new string[] { "RE_Customer_Type", "RE_Customer_Id", "Bill_To_Contact_Id" });

                        //Disable the Quantity when it is a serialized product. Else keep it enabled.
                        if (productSerialNumber != null || !(string.Equals(TypeConvert.ToString(productType), "Regular") || 
                            string.Equals(TypeConvert.ToString(productType), "Service")))
                            EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "Quantity", orderProducts.Rows.Count - 1, false);
                        else
                            EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "Quantity", orderProducts.Rows.Count - 1, true);

                        //NN 30-05-2013:Disable "Add Apple Care" checkbox if Product->Re_Apple_Care_product_Id is NULL.
                        if (Convert.IsDBNull(orderProduct["Product_Id__RE_Apple_Care_Prod"]))
                        {
                            EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_AppleCare_Product", rowIndex, false);
                        }
                        else
                        {
                            EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_AppleCare_Product", rowIndex, true);
                        }

                        //NN 20-06-2013:Setting RE_AppleCare_Product checkbox as true if the AppleCare Product is added before the primary Product.
                        if(!Convert.IsDBNull(orderProduct["RE_Product_Serial_No_Id@Rn_Descriptor"]))
                        {
                            DataRow[] appleCareProducts = orderProducts.AsEnumerable().Where(a => TypeConvert.ToString(a["RE_RAE_Serial_Number"]) ==
                                                                                 TypeConvert.ToString(orderProduct["RE_Product_Serial_No_Id@Rn_Descriptor"])).ToArray();

                            if (appleCareProducts != null && appleCareProducts.Length > 0)
                                orderProduct["RE_AppleCare_Product"] = true;
                        }
                    }
                    else if (storageLoc != null && storageLoc.Rows.Count > 1)
                    {
                        PivotalMessageBox.Show("Multiple Sales Locations are defined for the Store." + Environment.NewLine +
                            "Please contact the Administrator.", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    }
                    else
                    {
                        PivotalMessageBox.Show("No Sales Location defined for the Store." + Environment.NewLine + "Please contact the Administrator.",
                        MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    }
                }
                else if (price != null && price.Rows.Count > 1)
                    PivotalMessageBox.Show("Multiple pricing defined for the Product and the Currency." + Environment.NewLine + "Please contact the Administrator.",
                        MessageBoxButtons.OK, MessageBoxIcon.Stop);
                else
                    PivotalMessageBox.Show("No pricing data found for the Product and the Currency." + Environment.NewLine + "Please contact the Administrator.",
                            MessageBoxButtons.OK, MessageBoxIcon.Stop);                
            }
            catch (Exception exc)
            {
                Globals.HandleException(exc, true);
            }
            return added;
        }

        /// <summary>
        /// Update Item Scanned flag to true for the scanned Promotion product.
        /// </summary>
        /// <param name="product"></param>
        private bool UpdateItemScannedForPromotion(DataTable product)
        {
            bool rowUpdated = false;
            DataRow[] promotionProduct = this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"].AsEnumerable().Where(a => 
                (Id.Create(a["Product_Id"]) == Id.Create(product.Rows[0]["Product_Id"])) && !Convert.IsDBNull(a["RE_Promo_Ref_Serial"]) && 
                !TypeConvert.ToBoolean(a["RE_Item_Scanned"])).ToArray();
            //DS: 08052013 - When the same product is added in the Add-On grid 2 times, then we need to allow the cashier to scan the product instead of adding new.
            //So every time the item is scanned it will keep marking the item scanned from top to bottom.
            //if (promotionProduct != null && promotionProduct.Length == 1)
            if (promotionProduct != null && promotionProduct.Length > 0)
            {
                promotionProduct[0]["RE_Item_Scanned"] = true;
                //NN 28062013 - Added code to set the RE_Product_Serial_No_Id if the scanned Promotion itenm is a serialized item.
                if(product.TableName == "RE_Product_Serial_No")
                    promotionProduct[0]["RE_Product_Serial_No_Id"] = product.Rows[0]["RE_Product_Serial_No_Id"];
                                                    
                rowUpdated = true;
                HighlightRows();                
            }
            return rowUpdated;
        }

        /// <summary>
        /// Configure promotion.
        /// </summary>
        /// <param name="dataRow">Order Product row for which the Promotion is configured.</param>
        private void ConfigurePromotion(DataRow orderProduct)
        {
            #region Mandatory Tier-1 Promotions
            DataTable mandatoryPromotions = Globals.GetDataTable("RE_Mandatory Promo for Prod? CustType? Store?", new object[] { orderProduct["Product_Id"],
                        this.PrimaryDataRow["RE_Customer_Type"], this.PrimaryDataRow["RE_Store_Id"], this.PrimaryDataRow["RE_Store_Id"] }, new string[] { });
            
            if (mandatoryPromotions != null && mandatoryPromotions.Rows.Count > 0)
            {
                //Configure Tier-1 Mandatory Promotion.
                Tier1Promotions(orderProduct, mandatoryPromotions, true);
                Globals.SelectedPromotions = null;
            }
            #endregion
            else
            {
                #region Non-Mandatory Tier-1 Promotions
                //Non-Mandatory Tier-1 Promotions. Use can select not to choose any.
                DataTable nonMandatoryPromotions = Globals.GetDataTable("RE_Tier1 Promo for Prod? CustType? Store?", new object[] { orderProduct["Product_Id"],
                        this.PrimaryDataRow["RE_Customer_Type"], this.PrimaryDataRow["RE_Store_Id"], this.PrimaryDataRow["RE_Store_Id"] }, new string[] { });

                if (nonMandatoryPromotions != null && nonMandatoryPromotions.Rows.Count > 0)
                {
                    //Configure Tier-1 Non-Mandatory Promotion.
                    Tier1Promotions(orderProduct, nonMandatoryPromotions, false);
                    Globals.SelectedPromotions = null;
                }
                #endregion
            }
            #region Non-Mandatory Tier-2 Promotions
            //Go for Tier-2 Promotions.
            DataTable tier2Promotions = Globals.GetDataTable("RE_Tier2 Promo for Prod? CustType? Store?", new object[] { orderProduct["Product_Id"],
                        this.PrimaryDataRow["RE_Customer_Type"], this.PrimaryDataRow["RE_Store_Id"], this.PrimaryDataRow["RE_Store_Id"] }, new string[] { });

            if (tier2Promotions != null && tier2Promotions.Rows.Count > 0)
            {
                //Configure Tier-1 Mandatory Promotion.
                ShowPromotionList("Tier 2", false, orderProduct["Product_Id"]);
                if (Globals.SelectedPromotions != null && Globals.SelectedPromotions.Count > 0)
                {
                    //NN 19082013: Setting the variable promotionsCount as promotionsCount + the Items selected by users as Tier2 Promotions.
                    promotionsCount = promotionsCount + Globals.SelectedPromotions.Count;
                    foreach (object promotionSelected in Globals.SelectedPromotions)
                    {
                        //Fetch the items for this promotion and add then to the grid along with the Promotion discount.
                        DataRow[] promotionRows = tier2Promotions.AsEnumerable().Where(a => Id.Equals(Id.Create(a["Promotion_Id"]), Id.Create(promotionSelected))).ToArray();

                        switch (TypeConvert.ToString(promotionRows[0]["Type"]))
                        {
                            case "Purchase with Purchase":
                                //All the new Products to be added are of Type AddOn.
                                DataTable orderProducts = this.FormData.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
                                foreach (DataRow promotion in promotionRows)
                                { 
                                        //Add products to the grid.
                                    if (TypeConvert.ToInt16(promotion["Inventory_Quantity"]) > 0)
                                    {
                                        DataTable price = Globals.GetDataTable("RE_SFA Product Price with Product ? and Currency ? and LOB ?",
                                            new object[] { promotion["AddOn_Product_Id"], this.PrimaryDataRow["SFA_Currency_Id"], this.PrimaryDataRow["RE_LOB_Id"] }, "Price");

                                        if (price != null && price.Rows.Count == 1)
                                        {
                                            base.NewSecondaryRecord("SFA_Order__Product_SFA_Order_I");
                                            DataRow orderProductNewRow = orderProducts.Rows[orderProducts.Rows.Count - 1];
                                            orderProductNewRow["Product_Id"] = promotion["AddOn_Product_Id"];
                                            orderProductNewRow["RE_Product_Type"] = Globals.ServerSqlIndex("Product", "RE_Product_Type", Id.Create(promotion["AddOn_Product_Id"]));
                                            orderProductNewRow["RE_Invisible"] = false;
                                            orderProductNewRow["RE_Storage_Location_Id"] = orderProduct["RE_Storage_Location_Id"];
                                            orderProductNewRow["RE_From_Source_Order"] = false;
                                            orderProductNewRow["Quantity"] = 1;
                                            //For Inventoried Item only, mark this as false
                                            if (TypeConvert.ToBoolean(promotion["Inventoried"]))
                                                orderProductNewRow["RE_Item_Scanned"] = false;
                                            else
                                                orderProductNewRow["RE_Item_Scanned"] = true;
                                            orderProductNewRow["RE_Promo_Ref_Serial"] = orderProduct["RE_Product_Serial_No_Id__Seria"];
                                            orderProductNewRow["RE_Mandatory_Promotion"] = false;
                                            //orderProductNewRow["RE_Promotion_Id"] = promotionSelected;

                                            orderProduct["RE_Mandatory_Promotion"] = false;
                                            orderProduct["RE_Promotion_Id"] = promotionSelected;

                                            if (this.PrimaryDataRow["RE_Staff_Code"] != DBNull.Value)
                                            {
                                                orderProductNewRow["RE_Staff_Code"] = this.PrimaryDataRow["RE_Staff_Code"];
                                                orderProductNewRow["RE_Staff_Id"] = this.PrimaryDataRow["RE_Staff_Id"];
                                            }

                                            orderProductNewRow["Unit_Price"] = TypeConvert.ToDouble(price.Rows[0]["Price"]);

                                            //NN 20-06-2013: Added code for AppleCareItem added as promotion item
                                            if (TypeConvert.ToString(orderProductNewRow["RE_Product_Type"]) == "Apple Care")
                                            {
                                                DataRow[] appleCareProduct = orderProducts.AsEnumerable().Where(a => a["RE_RAE_Serial_Number"].ToString() == orderProduct["RE_Product_Serial_No_Id__Seria"].ToString() &&
                                                                        Id.Create(a["Product_Id"]) == Id.Create(promotion["AddOn_Product_Id"])).ToArray();
                                                if (appleCareProduct != null && appleCareProduct.Length > 0)
                                                {
                                                    foreach (DataColumn dc in orderProducts.Columns)
                                                    {
                                                        if (dc.ColumnName.ToUpper() != "SFA_ORDER__PRODUCT_ID" && dc.ColumnName.ToUpper() != "@BOOKMARK")
                                                            orderProductNewRow[dc.ColumnName] = appleCareProduct[0][dc.ColumnName];
                                                    }
                                                    orderProducts.Rows.Remove(appleCareProduct[0]);
                                                }

                                                orderProductNewRow["RE_RAE_Serial_Number"] = orderProductNewRow["RE_Promo_Ref_Serial"];
                                                orderProduct["RE_AppleCare_Product"] = true;
                                                orderProductNewRow["RE_Item_Scanned"] = true;
                                                orderProductNewRow["RE_RAE_Purchase_Mode"] = "C";

                                                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_AppleCare_Product", orderProducts.Rows.IndexOf(orderProduct), false);
                                            }

                                            CommonFieldPopulate(orderProductNewRow);
                                            Globals.EnableDisableSecondaryRow(false, "SFA_Order__Product_SFA_Order_I", orderProducts.Rows.Count - 1);
                                            EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Staff_Code", orderProducts.Rows.Count - 1, true);
                                            EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", orderProducts.Rows.Count - 1, false);
                                        }
                                    }
                                    
                                }
                                //Add extra item as type = promotion.
                                AddPromotionProduct(orderProduct, promotionRows, promotionSelected, false);
                                break;
                            default:
                                break;
                        }
                    }
                    TotalsSectionCalculations();
                }
            }
            #endregion

            HighlightRows();
        }

        /// <summary>
        /// Show the Promotion selection list to choose from.
        /// </summary>
        /// <param name="tier"></param>
        /// <param name="mandatory"></param>
        /// <param name="productId"></param>
        private void ShowPromotionList(string tier, bool mandatory,object productId)
        {
            TransitionPointParameter transParam = new TransitionPointParameter();
            ParameterList param = new ParameterList();
            transParam.Construct();
            transParam.SetUserDefinedParameter(1, tier);
            transParam.SetUserDefinedParameter(2, mandatory);
            transParam.SetUserDefinedParameter(3, productId);
            transParam.SetUserDefinedParameter(4, this.PrimaryDataRow["RE_Customer_Type"]);
            transParam.SetUserDefinedParameter(5, this.PrimaryDataRow["RE_Store_Id"]);
            transParam.SetUserDefinedParameter(6, this.PrimaryDataRow["RE_Store_Id"]);
            transParam.CopyToParameterList(param);

            Globals.ShowModalForm("System", Id.Create("0x0000000000000001"), param);
        }

        /// <summary>
        /// Common call for both Mandatory and Non-Mandatory Promotions.
        /// </summary>
        /// <param name="orderProduct"></param>
        /// <param name="promotions"></param>
        /// <param name="mandatory"></param>
        private void Tier1Promotions(DataRow orderProduct, DataTable promotions, bool mandatory)
        {
            ShowPromotionList("Tier 1", mandatory, orderProduct["Product_Id"]);
            if (mandatory)
            {
                while (Globals.SelectedPromotions == null || Globals.SelectedPromotions.Count == 0)
                {
                    ShowPromotionList("Tier 1", mandatory, orderProduct["Product_Id"]);
                }
            }
            if (Globals.SelectedPromotions != null && Globals.SelectedPromotions.Count == 1)
            {
                //Fetch the items for this promotion and add then to the grid along with the Promotion discount.
                DataRow[] promotionRows = promotions.AsEnumerable().Where(a => Id.Equals(Id.Create(a["Promotion_Id"]), Id.Create(Globals.SelectedPromotions[0]))).ToArray();

                //NN 19082013: Setting the variable promotionsCount as promotionsCount + the Items selected by users as Tier1 Promotions.
                promotionsCount = promotionsCount + Globals.SelectedPromotions.Count;

                switch (TypeConvert.ToString(promotionRows[0]["Type"]))
                {
                    case "Top-Up":
                    case "Free":
                        //All the new Products to be added are of Type AddOn.
                        DataTable orderProducts = this.FormData.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
                        foreach (DataRow promotion in promotionRows)
                        {                            
                                //Add products to the grid.
                            if (TypeConvert.ToInt16(promotion["Inventory_Quantity"]) > 0)
                            {
                                DataTable price = Globals.GetDataTable("RE_SFA Product Price with Product ? and Currency ? and LOB ?",
                                    new object[] { promotion["AddOn_Product_Id"], this.PrimaryDataRow["SFA_Currency_Id"], this.PrimaryDataRow["RE_LOB_Id"] }, "Price");

                                if (price != null && price.Rows.Count == 1)
                                {
                                    base.NewSecondaryRecord("SFA_Order__Product_SFA_Order_I");
                                    DataRow orderProductNewRow = orderProducts.Rows[orderProducts.Rows.Count - 1];
                                    orderProductNewRow["Product_Id"] = promotion["AddOn_Product_Id"];
                                    orderProductNewRow["RE_Product_Type"] = Globals.ServerSqlIndex("Product", "RE_Product_Type", Id.Create(promotion["AddOn_Product_Id"]));
                                    orderProductNewRow["RE_Invisible"] = false;
                                    orderProductNewRow["RE_Storage_Location_Id"] = orderProduct["RE_Storage_Location_Id"];
                                    orderProductNewRow["RE_From_Source_Order"] = false;
                                    orderProductNewRow["Quantity"] = 1;
                                    //For Inventoried Item only, mark this as false
                                    if (TypeConvert.ToBoolean(promotion["Inventoried"]))
                                        orderProductNewRow["RE_Item_Scanned"] = false;
                                    else
                                        orderProductNewRow["RE_Item_Scanned"] = true;
                                    orderProductNewRow["RE_Promo_Ref_Serial"] = orderProduct["RE_Product_Serial_No_Id__Seria"];
                                    orderProductNewRow["RE_Mandatory_Promotion"] = false;
                                    //orderProductNewRow["RE_Promotion_Id"] = Globals.SelectedPromotions[0];

                                    orderProduct["RE_Mandatory_Promotion"] = mandatory;
                                    orderProduct["RE_Promotion_Id"] = Globals.SelectedPromotions[0];

                                    if (this.PrimaryDataRow["RE_Staff_Code"] != DBNull.Value)
                                    {
                                        orderProductNewRow["RE_Staff_Code"] = this.PrimaryDataRow["RE_Staff_Code"];
                                        orderProductNewRow["RE_Staff_Id"] = this.PrimaryDataRow["RE_Staff_Id"];
                                    }

                                    orderProductNewRow["Unit_Price"] = TypeConvert.ToDouble(price.Rows[0]["Price"]);

                                    //NN 20-06-2013: Added code for AppleCareItem added as promotion item
                                    if (TypeConvert.ToString(orderProductNewRow["RE_Product_Type"]) == "Apple Care")
                                    {
                                        DataRow[] appleCareProduct = orderProducts.AsEnumerable().Where(a => a["RE_RAE_Serial_Number"].ToString() == orderProduct["RE_Product_Serial_No_Id__Seria"].ToString() &&
                                                                Id.Create(a["Product_Id"]) == Id.Create(promotion["AddOn_Product_Id"])).ToArray();
                                        if (appleCareProduct != null && appleCareProduct.Length > 0)
                                        {
                                            foreach (DataColumn dc in orderProducts.Columns)
                                            {
                                                if (dc.ColumnName.ToUpper() != "SFA_ORDER__PRODUCT_ID" && dc.ColumnName.ToUpper() != "@BOOKMARK" && dc.ColumnName.ToUpper() != "RE_PROMO_REF_SERIAL")
                                                    orderProductNewRow[dc.ColumnName] = appleCareProduct[0][dc.ColumnName];
                                            }
                                            orderProducts.Rows.Remove(appleCareProduct[0]);
                                        }

                                        orderProductNewRow["RE_RAE_Serial_Number"] = orderProductNewRow["RE_Promo_Ref_Serial"];
                                        orderProduct["RE_AppleCare_Product"] = true;
                                        orderProductNewRow["RE_Item_Scanned"] = true;
                                        orderProductNewRow["RE_RAE_Purchase_Mode"] = "C";

                                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_AppleCare_Product", orderProducts.Rows.IndexOf(orderProduct), false);
                                    }
                                    CommonFieldPopulate(orderProductNewRow);
                                    Globals.EnableDisableSecondaryRow(false, "SFA_Order__Product_SFA_Order_I", orderProducts.Rows.Count - 1);
                                    EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Staff_Code", orderProducts.Rows.Count - 1, true);
                                    EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", orderProducts.Rows.Count - 1, false);
                                }
                            }
                        }
                        //Add extra item as type = promotion.
                        AddPromotionProduct(orderProduct, promotionRows, Globals.SelectedPromotions[0], false);
                        TotalsSectionCalculations();
                        break;
                    case "Rebate":
                        AddPromotionProduct(orderProduct, promotionRows, Globals.SelectedPromotions[0], true);
                        TotalsSectionCalculations();
                        break;
                    default:
                        break;
                }
            }
        }

        /// <summary>
        /// Add the Promotion Product Item.
        /// </summary>
        /// <param name="orderProduct"></param>
        /// <param name="promotionRows"></param>
        /// <param name="rebate"></param>
        private void AddPromotionProduct(DataRow orderProduct, DataRow[] promotionRows, object promotionId, bool rebate)
        {
            DataTable promotionProduct = Globals.GetDataTable("RE_Products with Type as Promotion", new object[] { }, "Product_Id");
            if (promotionProduct != null && promotionProduct.Rows.Count == 1)
            {
                DataTable orderProducts = this.FormData.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
                base.NewSecondaryRecord("SFA_Order__Product_SFA_Order_I");
                DataRow orderProductPromotionRow = orderProducts.Rows[orderProducts.Rows.Count - 1];
                orderProductPromotionRow["Product_Id"] = promotionProduct.Rows[0]["Product_Id"];
                orderProductPromotionRow["RE_Product_Type"] = "Promotion";
                orderProductPromotionRow["RE_Invisible"] = false;
                orderProductPromotionRow["RE_Storage_Location_Id"] = orderProduct["RE_Storage_Location_Id"];
                orderProductPromotionRow["RE_From_Source_Order"] = false;
                orderProductPromotionRow["Quantity"] = 1;
                orderProductPromotionRow["RE_Item_Scanned"] = true;
                //orderProductPromotionRow["RE_Promotion_Id"] = promotionId;
                orderProductPromotionRow["RE_Promo_Ref_Serial"] = orderProduct["RE_Product_Serial_No_Id__Seria"];
                orderProductPromotionRow["RE_Mandatory_Promotion"] = false;
                orderProductPromotionRow["RE_Comments"] = promotionRows[0]["Promotion_Description"];

                if (rebate)
                {
                    orderProduct["RE_Mandatory_Promotion"] = true;
                    orderProduct["RE_Promotion_Id"] = promotionId;
                }
                if (!Convert.IsDBNull(this.PrimaryDataRow["RE_Staff_Code"]))
                {
                    orderProductPromotionRow["RE_Staff_Code"] = this.PrimaryDataRow["RE_Staff_Code"];
                    orderProductPromotionRow["RE_Staff_Id"] = this.PrimaryDataRow["RE_Staff_Id"];
                }

                orderProductPromotionRow["Unit_Price"] = -TypeConvert.ToDouble(promotionRows[0]["Effective_Discount"]);
                CommonFieldPopulate(orderProductPromotionRow);
                Globals.EnableDisableSecondaryRow(false, "SFA_Order__Product_SFA_Order_I", orderProducts.Rows.Count - 1);
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Staff_Code", orderProducts.Rows.Count - 1, true);
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", orderProducts.Rows.Count - 1, false);
            }
        }

        /// <summary>
        /// Highlight the rows to show the promotion products which are not scanned.
        /// </summary>
        private void HighlightRows()
        {
            PivotalSecondary pvtSecondary = this.FormControl.GetControlByName("SFA_Order__Product_SFA_Order_Id") as PivotalSecondary;

            if (pvtSecondary != null && pvtSecondary.Rows.Count > 0)
            {
                for (int i = 0; i < pvtSecondary.Rows.Count; i++)
                {
                    //Item not-scanned.
                    if (!TypeConvert.ToBoolean(pvtSecondary.Rows[i].Cells["RE_Item_Scanned"].Value))
                        pvtSecondary.Rows[i].DefaultCellStyle.BackColor = System.Drawing.Color.OrangeRed;
                    //Item scanned and it is a promotion product.
                    else if (TypeConvert.ToBoolean(pvtSecondary.Rows[i].Cells["RE_Item_Scanned"].Value) &&
                        !Convert.IsDBNull(pvtSecondary.Rows[i].Cells["RE_Promo_Ref_Serial"].Value))
                        pvtSecondary.Rows[i].DefaultCellStyle.BackColor = System.Drawing.Color.YellowGreen;
                    //Item is not a Promotion product.
                    else
                    {
                        if (i % 2 == 0)
                            pvtSecondary.Rows[i].DefaultCellStyle.BackColor = Color.FromArgb(255, 255, 255);
                        else
                            pvtSecondary.Rows[i].DefaultCellStyle.BackColor = Color.FromArgb(231, 239, 255);
                    }
                    //DS: 12052013 - When we come back from the Authorization/Tender screen, for a record coming from Source Order, we need to disable the Staff code and the DC.
                    if (TypeConvert.ToBoolean(pvtSecondary.Rows[i].Cells["RE_From_Source_Order"].Value))
                    {
                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Staff_Code", i, false);
                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", i, false);
                    }
                }
            }
        }

        /// <summary>
        /// Common method for topic/task/button for refund
        /// </summary>
        public void RefundStub()
        {
            if (this.FormView.Dirty)
            {
                if (PivotalMessageBox.Show("Changes to 'New Sale' will be lost if you navigate away." + Environment.NewLine +
                    "Click OK to continue, or Cancel to stay on the current record.", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
                    OpenRefundSale();
                else
                    return;
            }
            else
                OpenRefundSale();
        }

        /// <summary>
        /// Calculate total quantity, discount, subtotal, tax amount and total
        /// </summary>
        private void TotalsSectionCalculations()
        {
            int quantity = 0;
            double subtotal = 0;
            double discamount = 0;
            double taxamount = 0;
            double fulltotal = 0;
            double totalBD = 0;

            DataTable orderProducts = this.FormData.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
            if (orderProducts != null)
            {
                foreach (DataRow dr in orderProducts.Rows)
                {
                    quantity += TypeConvert.ToInt32(dr["Quantity"]);
                    discamount += TypeConvert.ToDouble(dr["Tier1_Discount_Value"]);
                    fulltotal += TypeConvert.ToDouble(dr["RE_Extended_Price"]);
                    subtotal += TypeConvert.ToDouble(dr["RE_Revenue"]);
                    taxamount += TypeConvert.ToDouble(dr["Tax_Amount"]);
                    totalBD += TypeConvert.ToDouble(dr["Unit_Price"]) * TypeConvert.ToDouble(dr["Quantity"]);
                }

                this.PrimaryDataRow["RE_Total_Qty"] = quantity;
                //DS: 12052013 - To cope with the Machine Epsilon Issue.
                this.PrimaryDataRow["Quote_Sub_Total"] = Math.Round(subtotal, 2);
                this.PrimaryDataRow["Total_Taxes"] = Math.Round(taxamount, 2);
                this.PrimaryDataRow["Quote_Total"] = Math.Round(fulltotal, 2);
                //Total Price before Discount.
                this.PrimaryDataRow["RE_Total_Price_BD"] = Math.Round(totalBD, 2);

                //Calculate the Discount from the rebates.
                this.PrimaryDataRow["Total_Discount"] = Math.Round(orderProducts.AsEnumerable().Where(a => String.Equals(TypeConvert.ToString(a["RE_Product_Type"]), "Promotion"))
                    .Sum(a => Math.Abs(TypeConvert.ToDouble(a["RE_Extended_Price"]))) + discamount, 2);
            }
        }

        ////DS: 27062013 - Now the receipt number generation happens on the Server side only.
        /// <summary>
        /// Auto-generate Receipt Number 
        /// </summary>
        //private void AutoGenerateReceiptNum()
        //{
        //    try
        //    {
        //        DataTable onlineStoreOfflinePOS = null;
        //        //DS: For Offline mode, use the Next_Number available on RE_Store_POS, else use the one in RE_Store
        //        if (SystemClient.SystemInformation.IsMobile)
        //            onlineStoreOfflinePOS = Globals.GetDataTable("RE_POS for Current User", new object[] { }, "Receipt_No_Prefix", "No_Of_Digits", "Next_Number");
        //        else
        //            onlineStoreOfflinePOS = Globals.GetDataTable("RE_Stores for Store ?", new object[] { this.PrimaryDataRow["RE_Store_Id"] }, "Receipt_No_Prefix", 
        //                "No_Of_Digits", "Next_Number");

        //        if (onlineStoreOfflinePOS != null && onlineStoreOfflinePOS.Rows.Count > 0)
        //        {
        //            //DS: When the Next_Number is null, start the series from 1 instead of 0. Remove the '-' from the merging.
        //            this.PrimaryDataRow["RE_Receipt_Number"] = TypeConvert.ToString(onlineStoreOfflinePOS.Rows[0]["Receipt_No_Prefix"]) +
        //                TypeConvert.ToString((Convert.IsDBNull(onlineStoreOfflinePOS.Rows[0]["Next_Number"]) ? 1 : onlineStoreOfflinePOS.Rows[0]["Next_Number"])).PadLeft(TypeConvert.ToInt32(onlineStoreOfflinePOS.Rows[0]["No_Of_Digits"]), '0');

        //            Globals.SystemClient.ExecuteServerTask("RE_Sale", "IncrementReceiptNumber", new Type[] {typeof(object)}, new object[] { onlineStoreOfflinePOS });
        //        }
        //    }
        //    catch (Exception exc)
        //    {
        //        Globals.HandleException(exc);
        //    }
        //}

        /// <summary>
        /// Hide/Show the group boxes according to the logic.
        /// </summary>
        /// <param name="Section_Visibility">Key of the dictionary is Section and the value is the visibility.</param>
        private void HideSections(Dictionary<string, bool> Section_Visibility)
        {
            if (Section_Visibility.Count > 0)
            {
                foreach (KeyValuePair<string, bool> pair in Section_Visibility)
                {
                    ((CdcSoftware.Pivotal.Engine.UI.Forms.PivotalGroupBox)this.FormControl.GetControlByName(pair.Key)).Visible = pair.Value;
                }
            }
        }

        /// <summary>
        /// Opens a new Sale form in the Deposit mode.
        /// </summary>
        private void OpenDepositSale()
        {
            TransitionPointParameter transitionParams = new TransitionPointParameter();
            transitionParams.Construct();
            transitionParams.SetUserDefinedParameter(5, "Deposit");

            //Close the previous Sales screen that's in the background
            this.FormView.CloseForm(true);
            Globals.NewForm("RE_Sale – Walk In", transitionParams.ParameterList, ActionTargetWindow.Current);
        }

        /// <summary>
        /// Opens a new Sale form in the Trade-In mode.
        /// </summary>
        private void OpenTradeInSale()
        {
            TransitionPointParameter transitionParams = new TransitionPointParameter();
            transitionParams.Construct();
            transitionParams.SetUserDefinedParameter(6, "Trade-In");

            //Close the previous Sales screen that's in the background
            this.FormView.CloseForm(true);
            Globals.NewForm("RE_Sale – Walk In", transitionParams.ParameterList, ActionTargetWindow.Current);
        }

        /// <summary>
        /// Opens a new Sale form in the Exchange mode.
        /// </summary>
        private void OpenExchangeSale()
        {
            TransitionPointParameter transitionParams = new TransitionPointParameter();
            transitionParams.Construct();
            transitionParams.SetUserDefinedParameter(1, "Exchange");

            //Close the previous Sales screen that's in the background
            this.FormView.CloseForm(true);
            Globals.NewForm("RE_Sale – Walk In", transitionParams.ParameterList, ActionTargetWindow.Current);
        }

        /// <summary>
        /// Open Refund sale for the form.
        /// </summary>
        /// <param name="formView"></param>
        private void OpenRefundSale()
        {
            TransitionPointParameter tParams = new TransitionPointParameter();
            tParams.Construct();
            tParams.SetUserDefinedParameter(3, "Refund");

            //Close the previous Sales screen that's in the background
            this.FormView.CloseForm(true);
            Globals.NewForm("RE_Sale – Walk In", tParams.ParameterList, ActionTargetWindow.Current);
        }
                
        /// <summary>
        /// Opens the portal page.
        /// </summary>
        /// <param name="portalName">Name of the portal to load.</param>
        private void OpenActiveSearchPage(string ActiveSearchPage)
        {
            IActionService _actionService = ClientContext.ClientAPIService.GetService<IActionService>();
            IActiveSearchPageActionTarget target = _actionService.CreateActionTarget<IActiveSearchPageActionTarget>();

            target.ActiveSearchPage = ActiveSearchPage;
            IAction action = _actionService.CreateAction(string.Empty, ActionCommand.Show, ActionContent.ActiveSearchPage, target);
            action.SaveInHistory = false;
            action.TargetWindow = ActionTargetWindow.Current;
            _actionService.ExecuteAction(action);
        }

        /// <summary>
        /// Check if user has entered a greater quantity than what was ordered earlier, if so, set it to max quantity ordered earlier
        /// </summary>
        /// <param name="sourceOrderId"></param>
        /// <param name="productId"></param>
        /// <param name="quantity"></param>
        /// <param name="orderProduct"></param>
        /// <param name="rowIndex"></param>
        private void QuantityCheck(object sourceOrderId, object productId, int quantity, DataRow orderProduct, int rowIndex)
        {
            DataTable orderProducts = this.FormData.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
            Boolean qtymorethanordered = false;
            DataTable existingOrderProducts = Globals.GetDataTable("RE_Order Products with Order ? Product ? with Status as Processed and Type as Non refund",
                    new object[] { sourceOrderId, productId }, "SFA_Order__Product_Id", "Product_Id", "Quantity");

            if (existingOrderProducts != null && existingOrderProducts.Rows.Count > 0 && quantity < 0)
            {
                int orderedqty = TypeConvert.ToInt32(existingOrderProducts.Compute("SUM(Quantity)", string.Empty));
                int sumofqtys = orderProducts.AsEnumerable().Where(a => Id.Create(a["Product_Id"]) == Id.Create(productId) &&
                    TypeConvert.ToInt32(a["Quantity"]) < 0).Sum(a => Math.Abs(TypeConvert.ToInt32(a["Quantity"])));

                if (sumofqtys > orderedqty)
                {
                    PivotalMessageBox.Show("The quantity can't be more than: " + (orderedqty - sumofqtys - quantity).ToString() + '.', MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    qtymorethanordered = true;
                }
                if (qtymorethanordered)
                    orderProduct["Quantity"] = orderedqty - sumofqtys - quantity;
            }
            else
            {
                orderProduct["Quantity"] = Math.Abs(TypeConvert.ToInt32(orderProduct["Quantity"]));
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Staff_Code", rowIndex, true);
            }
        }
        
        /// <summary>
        /// Updates common fields.
        /// </summary>
        /// <param name="orderProduct"></param>
        private void CommonFieldPopulate(DataRow orderProduct)
        {
            double taxPercentage = TypeConvert.ToDouble(Globals.ServerSqlIndex("Employee", "RE_Tax_Rate", SystemClient.UserProfile.EmployeeId));
            orderProduct["Tax_Percentage"] = taxPercentage;
            double TotalPrice = 0;
            double Tier1Discount = 0;
            if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Exchange" || TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Refund")
            {
                TotalPrice = TypeConvert.ToDouble(orderProduct["Unit_Price"]) * Math.Abs(TypeConvert.ToInt32(orderProduct["Quantity"]));
                Tier1Discount = Math.Abs(TypeConvert.ToDouble(orderProduct["Tier1_Discount_Value"]));
            }
            else
            {
                TotalPrice = TypeConvert.ToDouble(orderProduct["Unit_Price"]) * TypeConvert.ToInt32(orderProduct["Quantity"]);
                Tier1Discount = (TypeConvert.ToDouble(orderProduct["Tier1_Discount_Value"]));
            }

            orderProduct["RE_Extended_Price"] = Globals.RoundOffPrice(TotalPrice - Tier1Discount, this.PrimaryDataRow["RE_LOB_Id"]);
            if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Exchange" || TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Refund")
            {
                if (TypeConvert.ToInt32(orderProduct["Quantity"]) < 0)
                    orderProduct["RE_Extended_Price"] = -TypeConvert.ToDouble(orderProduct["RE_Extended_Price"]);
            }

            //NN 11062013:
            //Fix for GST Trade-in issue. For Trade-in items "Tax_Amount" shoule be 0.
            if (string.Equals(TypeConvert.ToString(orderProduct["RE_Product_Type"]), "Trade-In"))
                orderProduct["Tax_Amount"] = 0;
            else
                orderProduct["Tax_Amount"] = Globals.RoundOffPrice(TypeConvert.ToDouble(orderProduct["RE_Extended_Price"]) * (1 - 1 / (1 + taxPercentage / 100)),
                    this.PrimaryDataRow["RE_LOB_Id"]);
            //DS: 12052013 - To cope with the Machine Epsilon Issue.
            orderProduct["RE_Revenue"] = Math.Round(TypeConvert.ToDouble(orderProduct["RE_Extended_Price"]) - TypeConvert.ToDouble(orderProduct["Tax_Amount"]), 2);
            orderProduct["RE_Unit_Cost_Price"] = Globals.RoundOffPrice(TypeConvert.ToDouble(Globals.ServerSqlIndex("Product", "SFA_Cost", Id.Create(orderProduct["Product_Id"])))
                * TypeConvert.ToInt32(orderProduct["Quantity"]),this.PrimaryDataRow["RE_LOB_Id"]);
            //DS: 12052013 - To cope with the Machine Epsilon Issue.
            orderProduct["RE_Profit"] = Math.Round(TypeConvert.ToDouble(orderProduct["RE_Revenue"]) - TypeConvert.ToDouble(orderProduct["RE_Unit_Cost_Price"]), 2);
        }

        /// <summary>
        /// Disable a particular datagrid cell.
        /// </summary>
        /// <param name="secondaryName">Secondary Data Name</param>
        /// <param name="cellName">Cell name to be made read-only.</param>
        /// <param name="rowIndex">Row index for the cell.</param>
        /// <param name="enableCell">true, will enable the field for editing.</param>
        private static void EnableDisableDataGridCell(string secondaryName, string cellName, int rowIndex, bool enableCell)
        {
            IFormView formView = (IFormView)ClientContext.ClientAPIService.GetActiveContentObject();
            CdcSoftware.Pivotal.Engine.UI.Forms.PivotalClientFormControl formControl = (CdcSoftware.Pivotal.Engine.UI.Forms.PivotalClientFormControl)formView.FormControl;

            // Get the Secondary Segment into a PivotalSecondary object...
            CdcSoftware.Pivotal.Engine.UI.Forms.PivotalSecondary secondary = formControl.GetSecondary(secondaryName);

            if (secondary != null)
                secondary.Rows[rowIndex].Cells[cellName].ReadOnly = !enableCell;
        }
                
        /// <summary>
        /// Set the visibility of the sections in the Sales screen.
        /// </summary>
        private void SetVisibilityOfSections()
        {
            Section_Visibility.Clear();
            if (string.Equals(TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]), "Walk-In"))
            {
                Section_Visibility.Add("PGBMemberInformation", false);
                Globals.SetFieldRequired(false, "Bill_To_Contact_Id");
                this.PrimaryDataRow["Bill_To_Contact_Id"] = DBNull.Value;
                this.PrimaryDataRow["RE_Customer_Id"] = DBNull.Value;
            }
            else if (string.Equals(TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]), "Member"))
            {
                Section_Visibility.Add("PGBMemberInformation", true);
                Globals.SetFieldRequired(true, "Bill_To_Contact_Id");
            }

            HideSections(Section_Visibility);
        }
        
        /// <summary>
        /// Shared code between OnFormInitialised and OnFormReloaded
        /// </summary>
        private void SharedLoad()
        {
            exchangeSecCell = ((CdcSoftware.Pivotal.Engine.UI.Forms.PivotalSecondary)this.FormControl.GetControlByName("SFA_Order__Product_SFA_Order_Id")).Columns["RE_Exchange_Reason"] as CdcSoftware.Pivotal.WindowsFormControls.DropDownColumn;
            refundSecCell = ((CdcSoftware.Pivotal.Engine.UI.Forms.PivotalSecondary)this.FormControl.GetControlByName("SFA_Order__Product_SFA_Order_Id")).Columns["RE_Refund_Reason"] as CdcSoftware.Pivotal.WindowsFormControls.TextBoxColumn;
            srcReceiptNo = (CdcSoftware.Pivotal.Engine.UI.Forms.PivotalTextBox)this.FormControl.GetControlByName("RESourceReceiptNo");

            if (this.PrimaryDataRow["RE_Product_Id"] != DBNull.Value)
            {
                ((PivotalForeignKey)this.FormControl.GetControlByDataName("RE_Product_Serial_No_Id")).ReadOnly = false;
                ((PivotalTextBox)this.FormControl.GetControlByDataName("RE_Serial_Number")).ReadOnly = false;
            }
            else
            {
                ((PivotalForeignKey)this.FormControl.GetControlByDataName("RE_Product_Serial_No_Id")).ReadOnly = true;
                ((PivotalTextBox)this.FormControl.GetControlByDataName("RE_Serial_Number")).ReadOnly = true;
            }    

            if (!Globals.CurrentUserInSecurityGroup("Retail Customer Service") && !Globals.CurrentUserInSecurityGroup("Retail POS"))
            {
                if (this.RecordId != null)
                {
                    EnableDisableButtons(true, "btnTender");
                    EnableDisableButtons(false, "btnHold", "btnCancel", "btnMemSearch", "btnFetch", "btnSalesSearch", "btnRePrint", "btnExchangeSale",
                        "btnRefund", "btnNewSale", "btnTradeIn", "btnDeposit", "btnTradeInItem", "btnFeesItem", "btnDepositItem", "btnProcessTxn","btnInstallbaseItem");
                }
            }

            Globals.RemoveButtonBarButton(new string[] { "Save", "Apply", "Refresh", "Delete", "Cancel" });
            //For new record
            if (this.RecordId == null)
            {
                if (this.TransitionPointParameter.UserDefinedParametersNumber == 1)
                {
                    this.PrimaryDataRow["RE_Type"] = "Exchange";
                    srcReceiptNo.ReadOnly = false;
                    exchangeSecCell.Visible = true;
                    ((CdcSoftware.Pivotal.Engine.UI.Forms.PivotalCheckBox)this.FormControl.GetControlByName("REGift")).Enabled = false;
                }
                else if (this.TransitionPointParameter.UserDefinedParametersNumber == 3)
                {
                    this.PrimaryDataRow["RE_Type"] = "Refund";
                    srcReceiptNo.ReadOnly = false;
                    refundSecCell.Visible = true;
                    ((CdcSoftware.Pivotal.Engine.UI.Forms.PivotalCheckBox)this.FormControl.GetControlByName("REGift")).Enabled = false;
                }
                else if (this.TransitionPointParameter.UserDefinedParametersNumber == 5)
                {
                    this.PrimaryDataRow["RE_Type"] = "Deposit";
                    EnableDisableButtons(true, "btnDepositItem");
                }
                else if (this.TransitionPointParameter.UserDefinedParametersNumber == 6)
                {
                    this.PrimaryDataRow["RE_Type"] = "Trade-In";
                    EnableDisableButtons(true, "btnTradeInItem");
                    ((CdcSoftware.Pivotal.Engine.UI.Forms.PivotalCheckBox)this.FormControl.GetControlByName("REGift")).Enabled = false;
                }

                //DS: 19042013 - This value is not used anywhere.
                //bool masterPOS = false;
                Id storePOSId = Id.Create(this.PrimaryDataRow["RE_POS_Id"]);
                //if (storePOSId != null)
                //    masterPOS = TypeConvert.ToBoolean(Globals.ServerSqlIndex("RE_Store_POS", "Master_POS", storePOSId));

                DataTable cashierLogsforCurrentBatch = null;

                if (this.SystemClient.SystemInformation.IsMobile)
                    cashierLogsforCurrentBatch = Globals.GetDataTable("RE_Cashier Log for Today for Current Store", new object[] { }, "Staff_Id", "Store_Id", "Batch_Id", "POS_Id");
                else
                    cashierLogsforCurrentBatch = Globals.GetDataTable("RE_All Cashier Logins for Today for In Progress Batch for Current Store ?",
                        new object[] { }, "Staff_Id", "Store_Id", "Batch_Id", "POS_Id");

                if (cashierLogsforCurrentBatch != null && cashierLogsforCurrentBatch.Rows.Count > 0)
                {
                    //DS: 20052013 - Fix for the case when multiple POS are there and there is one cashier logged-in to POS 1, then POS 2 was able to get into new Sale screen.
                    //However cashier was unable to complete the sale as the check for the POS is there in Tender again.
                    DataRow[] currentPOSCashierLogins = cashierLogsforCurrentBatch.AsEnumerable().Where(a => Id.Create(a["POS_Id"]) == storePOSId).ToArray();
                    if (currentPOSCashierLogins.Count() > 0)
                    {
                        this.PrimaryDataRow["RE_Cashier_Id"] = currentPOSCashierLogins[0]["Staff_Id"];
                        this.PrimaryDataRow["RE_Store_Id"] = currentPOSCashierLogins[0]["Store_Id"];
                        this.PrimaryDataRow["RE_Batch_Id"] = currentPOSCashierLogins[0]["Batch_Id"];
                    }
                }

                if (this.PrimaryDataRow["RE_Cashier_Id"] == DBNull.Value)
                {
                    this.FormView.CloseForm(true);
                    if (PivotalMessageBox.Show("No Cashier found logged in to the POS.", MessageBoxButtons.OK, MessageBoxIcon.Warning) == DialogResult.OK)
                        Globals.NewForm("RE_Cashier_Log", null);
                    return;
                }
                this.PrimaryDataRow["RE_Customer_Type"] = "Walk-In";
                if (this.RecordId == null && (this.TransitionPointParameter.UserDefinedParametersNumber == 1 ||
                    this.TransitionPointParameter.UserDefinedParametersNumber == 3))
                    this.FormControl.GetControlByDataName("RE_Source_Receipt_No").Focus();
                else
                    this.FormControl.GetControlByDataName("RE_Product_Barcode").Focus();

                EnableDisableButtons(false, "btnRePrint", "btnVoid", "btnVoidnNew", "btnCancel", "btnProcessTxn");
                if (string.Equals(TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]), "Deposit"))
                {
                    this.FormControl.GetControlByDataName("RE_Product_Barcode").Enabled = false;
                    this.FormControl.GetControlByDataName("RE_Product_Id").Enabled = false;
                }
                else
                {
                    this.FormControl.GetControlByDataName("RE_Product_Barcode").Enabled = true;
                    this.FormControl.GetControlByDataName("RE_Product_Id").Enabled = true;
                }
            }
            else
            {
                Globals.EnableDisableAllPrimaryFields(true);
                EnableDisableButtons(false, "btnHold", "btnVoid", "btnRePrint", "btnCancel", "btnVoidnNew", "btnProcessTxn");
                EnableDisableButtons(true, "btnFetch");

                //Once a product is added to the secondary(in the previous attempt) do not allow the user to update the Customer_Type and other fields
                //to which the default discount is associated.
                if (this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"] != null && this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"].Rows.Count > 0)
                    if (TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]) != "Walk-In")
                        Globals.EnableDisablePrimaryFields(false, new string[] { "RE_Customer_Type", "RE_Customer_Id", "Bill_To_Contact_Id" });

                if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Exchange")
                {
                    exchangeSecCell.Visible = true;
                    srcReceiptNo.ReadOnly = true;
                    //Disable Gift 
                    this.FormControl.GetControlByName("REGift").Enabled = false;
                }
                else
                    exchangeSecCell.Visible = false;

                if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Refund")
                {
                    refundSecCell.Visible = true;
                    srcReceiptNo.ReadOnly = true;
                    //Disable Gift 
                    this.FormControl.GetControlByName("REGift").Enabled = false;
                }
                else
                    refundSecCell.Visible = false;

                if (TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) != "Processed" && TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Trade-In")
                {
                    EnableDisableButtons(true, "btnTradeInItem");
                    EnableDisableButtons(false, "btnDepositItem");
                }
                else if (TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) != "Processed" && TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Deposit")
                {
                    EnableDisableButtons(true, "btnDepositItem");
                    EnableDisableButtons(false, "btnTradeInItem");
                    this.FormControl.GetControlByDataName("RE_Product_Barcode").Enabled = false;
                    this.FormControl.GetControlByDataName("RE_Product_Id").Enabled = false;
                }
                else
                    EnableDisableButtons(false, "btnTradeInItem", "btnDepositItem");

                if (TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) == "Processed")
                {
                    //Form should be readonly i.e. disable all fields (buttons are disconnected fields, so they wont)
                    Globals.EnableDisableAllFields(false, false, false);
                    EnableDisableButtons(false, "btnTradeInItem", "btnFeesItem", "btnDepositItem", "btnInstallbaseItem");
                    //Enabled only if Order/Sale date is today
                    if (TypeConvert.ToDateTime(this.PrimaryDataRow["RE_Order_Date"]).Date == DateTime.Today)
                        EnableDisableButtons(true, "btnRePrint", "btnVoid", "btnVoidnNew");
                    else
                        EnableDisableButtons(false, "btnRePrint", "btnVoid", "btnVoidnNew");

                    //NN18092013: Added code to disable the "btnVoidnNew" button when AppleCare is involved.
                    DataTable orderProduct = this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
                    DataRow[] appleCareProducts = orderProduct.AsEnumerable().Where(a => a["RE_RAE_Serial_Number"] != DBNull.Value).ToArray();
                    //Check if Apple Care Produtcs exists in this Order record.
                    if (appleCareProducts != null && appleCareProducts.Length > 0)
                    {
                        EnableDisableButtons(false, "btnVoidnNew");
                    }

                    if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Deposit" && TypeConvert.ToString(this.PrimaryDataRow["RE_Deposit_Status"]) == "Pending")
                        EnableDisableButtons(true, "btnProcessTxn");
                    else
                        EnableDisableButtons(false, "btnProcessTxn");
                }
                else if (TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) == "Void")
                {
                    Globals.EnableDisableAllFields(false, false, false);
                    //DS: 14082013 - When the sale is in status Void, there is must not keep the Fees and InstallBase button Enabled.
                    EnableDisableButtons(false, "btnRePrint", "btnVoid", "btnHold", "btnCancel", "btnVoidnNew", "btnTradeInItem", "btnDepositItem", "btnFeesItem", "btnInstallbaseItem");
                }
                else if (TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) == "Pending" || TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) == "Hold")
                    //DS: 14082013 - When the we open an saved Pending Record, the Fees and InstallBase button should be enabled.
                    EnableDisableButtons(true, "btnHold", "btnCancel", "btnFeesItem", "btnInstallbaseItem");

                if (TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) != "Processed" && TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) != "Void")
                {
                    //Disable the Quantity when it is a serialized product/Promotion Item. Else keep it enabled.
                    DataTable orderProducts = this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
                    if (orderProducts != null && orderProducts.Rows.Count > 0)
                    {
                        for (int i = 0; i < orderProducts.Rows.Count; i++)
                        {
                            if (!Convert.IsDBNull(orderProducts.Rows[i]["RE_Product_Serial_No_Id"]) || !Convert.IsDBNull(orderProducts.Rows[i]["RE_Promo_Ref_Serial"]) ||
                                !(string.Equals(TypeConvert.ToString(orderProducts.Rows[i]["RE_Product_Type"]), "Regular")
                                    || string.Equals(TypeConvert.ToString(orderProducts.Rows[i]["RE_Product_Type"]), "Service")))
                                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "Quantity", i, false);
                            else
                                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "Quantity", i, true);

                            //NN 31 May 2013:
                            //Added code to enable disable Apple Care fields in Product secondary.
                            if (Convert.IsDBNull(orderProducts.Rows[i]["Product_Id__RE_Apple_Care_Prod"]) || TypeConvert.ToInt16(orderProducts.Rows[i]["Quantity"]) < 0)
                                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_AppleCare_Product", i, false);
                            else
                                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_AppleCare_Product", i, true);
                        }
                    }
                }
            }

            SetVisibilityOfSections();

            this.EnableDisableVoucherAndDiscountColumn();
            
            this.FormView.Dirty = false;
        }

        /// <summary>
        /// Set a common set of secondary fields to null when Source order Id is not present
        /// </summary>
        /// <param name="orderProd">Datarow to be updated</param>
        /// Revision   Date        Author  Description
        /// 6.0.12.1   8/04/2013   DS      Initial Version
        /// </history>
        private void SetFieldsToNull(DataRow orderProd)
        {
            orderProd["RE_Discount_Condition1_Id"] = DBNull.Value;
            orderProd["Tier1_Discount_Percent"] = DBNull.Value;
            orderProd["Tier1_Discount_Value"] = DBNull.Value;
        }


        /// <summary>
        /// For the Order Product Row, enable/disable the DC and reconfigure them.
        /// </summary>
        /// <param name="args"></param>
        /// <param name="orderProduct"></param>
        private void RecalculateAndEnableDisableDisc(int rowIndex, DataRow orderProduct, bool positive)
        {
            SetFieldsToNull(orderProduct);

            //Recalculate discounts
            if (!ConfigureProductLevelDiscount(orderProduct["Product_Id"], orderProduct, rowIndex))
            {
                if (string.Equals(TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]), "Member"))
                {
                    //NN 24052013: Added code to set the postive value to false when RE_Discount_Condition1_Id is set as Member Discount.
                    MemberDiscount(orderProduct, rowIndex);
                    if(!Convert.IsDBNull(orderProduct["RE_Discount_Condition1_Id"]))
                        positive = false;
                }
                //else if (string.Equals(TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]), "Staff"))
                //    StaffDiscount(orderProduct);
                //else if (string.Equals(TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]), "Corporate"))
                //    MediaDiscount(orderProduct);
            }
            if (positive)
            {
                if (!TypeConvert.ToBoolean(orderProduct["RE_ProductLevelDisc"]) && TypeConvert.ToBoolean(orderProduct["Product_Id__RE_Discount_Applic"]))
                    EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", rowIndex, true);
            }
            else
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", rowIndex, false);

            //DS: Only when there is no source order, then make this field read-only.
            if (!Convert.IsDBNull(this.PrimaryDataRow["RE_Source_Order_Id"]))
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Staff_Code", rowIndex, false);
            else
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Staff_Code", rowIndex, true);
        }

        /// <summary>
        /// Update the product line item on change of customer type.
        /// </summary>
        /// <param name="MorSorMD"></param>
        private void UpdateOrderProductGrid(string MorSorMD)
        {
            //Check if there is Product in Grid. If so, then Calculate the discount conditions.
            int i = 0;
            foreach (DataRow orderProduct in this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"].Rows)
            {
                if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) != "Exchange" && TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) != "Refund")
                {
                    if (!ConfigureProductLevelDiscount(orderProduct["Product_Id"], orderProduct, i))
                    {
                        if (string.Equals(MorSorMD, "M"))
                            MemberDiscount(orderProduct,i);
                        //else if (string.Equals(MorSorMD, "S"))
                        //    StaffDiscount(orderProduct);
                        //else if (string.Equals(MorSorMD, "MD"))
                        //    MediaDiscount(orderProduct);
                        //For Top Management there is no default discount required.
                    }
                }
                else
                {
                    if (this.PrimaryDataRow["RE_Source_Order_Id"] != DBNull.Value)
                        UpdateExchangeDiscountCondition(Id.Create(this.PrimaryDataRow["RE_Source_Order_Id"]), orderProduct["Product_Id"], orderProduct, i);
                }

                //Call method to update the field values
                CommonFieldPopulate(orderProduct);

                i++;
            }
            //Calculate the Totals section values
            TotalsSectionCalculations();
        }

        /// <summary>
        /// Update the Discount conditions if any on SKU exists
        /// </summary>
        /// <param name="sourceOrderId">Source Order Id</param>
        /// <param name="productSKU">Product SKU</param>
        /// <param name="orderProduct">Datarow to be updated</param>
        /// <history>
        /// Revision   Date        Author  Description
        /// 6.0.12.1    8/04/2013  DS      Initial Version
        /// </history>
        private void UpdateExchangeDiscountCondition(Id sourceOrderId, object product, DataRow orderProduct, int rowIndex)
        {
            try
            {
                DataTable exchangeProducts = Globals.GetDataTable("RE_Order Products with Order ? Product ?", new object[] { sourceOrderId, product },
                    "RE_Discount_Condition1_Id", "Unit_Price", "RE_Staff_Id", "RE_Staff_Code", "RE_Voucher_Number");

                if (exchangeProducts != null && exchangeProducts.Rows.Count > 0)
                {
                    if (exchangeProducts.Rows[0]["Product_Id"] == DBNull.Value)
                        return;
                    else
                    {
                        orderProduct["RE_Voucher_Number"] = exchangeProducts.Rows[0]["RE_Voucher_Number"];
                        if (exchangeProducts.Rows[0]["RE_Discount_Condition1_Id"] != DBNull.Value)
                        {
                            orderProduct["RE_Discount_Condition1_Id"] = exchangeProducts.Rows[0]["RE_Discount_Condition1_Id"];
                            ApplyDiscount(true, orderProduct);
                        }
                        orderProduct["Unit_Price"] = exchangeProducts.Rows[0]["Unit_Price"];
                        orderProduct["RE_Staff_Id"] = exchangeProducts.Rows[0]["RE_Staff_Id"];
                        orderProduct["RE_Staff_Code"] = exchangeProducts.Rows[0]["RE_Staff_Code"];
                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Staff_Code", rowIndex, false);
                    }
                }
            }
            catch (Exception exc)
            {
                Globals.HandleException(exc);
            }
        }

        /// <summary>
        /// Enable/Disable Remaining Quota fields with the Tier and Member Qualification.
        /// </summary>
        private void EnableDisableRemainingQuota()
        {
            //By Default Hide the Remaining Quota For Birthday Promotion field. The field should be visible if the Loyalty Program Tier that 
            //the contact belongs to has the "Birthday Promotion" defined and the current month is the birthday month of the contact.
            if (TypeConvert.ToDateTime(this.PrimaryDataRow["Birthday"]).Month == DateTime.Now.Month &&
                TypeConvert.ToBoolean(this.PrimaryDataRow["Birthday_Promotion"]))
            {
                //Enable the fields to show the Ramaining Quota for Birthday Promotion.
                this.FormControl.GetControlByName("PivotalLabel3").Visible = true;
                this.FormControl.GetControlByName("PivotalTextBox1").Visible = true;

                //Fetch used for the current year for the contact id selected, and subtract from Loyalty Program Tier's (Contact's tier)
                //Birthday Promotion Quota. If no data is found for current year for the contact, the remaining quota would be the same 
                //as the tier quota.
                DataTable memberQuotaUsed = Globals.GetDataTable("RE_Member Birthday Discount with Member ? Year ?",
                    new object[] { this.PrimaryDataRow["Bill_To_Contact_Id"], DateTime.Now.Year }, "Used");
                if (memberQuotaUsed != null && memberQuotaUsed.Rows.Count > 0)
                {
                    this.PrimaryDataRow["Bday_Remaining_Quota"] = bDayQuota = TypeConvert.ToInt32(this.PrimaryDataRow["Bday_Promo_Quota"]) -
                        TypeConvert.ToInt32(memberQuotaUsed.Rows[0]["Used"]);
                }
                else
                {
                    this.PrimaryDataRow["Bday_Remaining_Quota"] = bDayQuota = TypeConvert.ToInt32(this.PrimaryDataRow["Bday_Promo_Quota"]);
                }
            }
            else
            {
                this.FormControl.GetControlByName("PivotalLabel3").Visible = false;
                this.FormControl.GetControlByName("PivotalTextBox1").Visible = false;
                this.PrimaryDataRow["Bday_Remaining_Quota"] = DBNull.Value;
            }
        }

        /// <summary>
        /// Used to enable/disbale RE_Voucher_Number column in Order__Product secondary depening on RE_Discount_Condition1_Id value
        /// </summary>
        /// <history>
        /// #Revision   Date        Author  Description
        /// 6.0.12.0    08/04/2013  DS      Initial Version
        /// </history>
        private void EnableDisableVoucherAndDiscountColumn()
        {
            try
            {
                DataTable orderProduct = this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
                int rowIndex = 0;
                
                foreach (DataRow orderProductRow in orderProduct.Rows)
                {
                    Id productId = null;
                    if (TypeConvert.ToBoolean(orderProductRow["RE_Discount_Condition1_Id__Vou"]))
                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Voucher_Number", rowIndex, true);
                    else
                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Voucher_Number", rowIndex, false);

                    //NN 08062013:Added Code to fix enabling/disabling issue for discountCondition in case of Product-Level discount.
                    if (!Convert.IsDBNull(orderProductRow["RE_Discount_Condition1_Id"]))
                        productId = Id.Create(Globals.SqlIndex("RE_Discount_Condition", "Product_Id", Id.Create(orderProductRow["RE_Discount_Condition1_Id"])));

                    if(productId == Id.Create(orderProductRow["Product_Id"]))
                        orderProductRow["RE_ProductLevelDisc"] = true;
                    else
                        orderProductRow["RE_ProductLevelDisc"] = false;

                    //DS:08102012 - Enable/Disable discount condition column based on the discount applicable field on.
                    if (!Convert.IsDBNull(orderProductRow["RE_Promo_Ref_Serial"]) || 
                        (TypeConvert.ToBoolean(orderProductRow["RE_ProductLevelDisc"]) || !TypeConvert.ToBoolean(orderProductRow["Product_Id__RE_Discount_Applic"])))
                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", rowIndex, false);

                    //NN:23052013 -  Enable/Disable discount condition column based on DiscountCondition->CustomerType value
                    //When CustomerType = System Member then diasble discount condition
                    if(TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]) == "Member" && 
                        TypeConvert.ToString(orderProductRow["RE_Discount_Condition1_Id__Cus"]) == "System Member")
                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", rowIndex, false);

                    rowIndex++;
                }
            }
            catch (Exception exc)
            {
                Globals.HandleException(exc);
            }
        }        

        /// <summary>
        /// Enable/Disable the buttons.
        /// </summary>
        /// <param name="enableButtons">true, will enable the buttons.</param>
        /// <param name="buttonsNames">Buttons names.</param>
        private void EnableDisableButtons(bool enableButtons, params string[] buttonsNames)
        {
            foreach (string btn in buttonsNames)
            {
                this.FormControl.GetControlByName(btn).Enabled = enableButtons;
            }
        }

        /// <summary>
        /// Check for availability of the inventory. If not warn the user.
        /// </summary>
        /// <param name="quantity">Quantity to be verified.</param>
        /// <param name="isFromQty"></param>
        /// <param name="productId"></param>
        /// <param name="orderProduct">If from qty, value will be there , otherwise it will be null</param>
        /// <returns>True if available otherwise false.</returns>
        private bool InventoryCheck(int quantity, bool isFromQty, object productId, DataRow orderProduct)
        {
            bool available = false;
            oldQty = previousQuantity;

            //For Non-Inventoried products, no need to check for the Inventory.
            if (!TypeConvert.ToBoolean(Globals.SqlIndex("Product", "RE_Inventoried", Id.Create(productId))))
                return true;

            //Check for Inventory. No Inventory, do not allow to add products. 
            DataTable stockAvailable = Globals.GetDataTable("RE_Inventory for Product? At current Store", new object[] { productId }, "Quantity_Actual");

            if (stockAvailable != null && stockAvailable.Rows.Count > 0 && TypeConvert.ToInt16(stockAvailable.Rows[0]["Quantity_Actual"]) >= 1)
            {
                int totalQty = this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"].AsEnumerable().Where(a => (Id.Create(a["Product_Id"]) == Id.Create(productId)
                    && TypeConvert.ToInt32(a["Quantity"]) > 0 && Convert.IsDBNull(a["RE_Promo_Ref_Serial"]))).Sum(a => TypeConvert.ToInt32(a["Quantity"]));

                if (!isFromQty)
                    totalQty = totalQty + 1;

                if (quantity > 0 && TypeConvert.ToInt32(stockAvailable.Rows[0]["Quantity_Actual"]) < totalQty)
                {
                    if (isFromQty)
                        popupShown = true;
                    PivotalMessageBox.Show("No more stock for the Product.", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    available = false;
                    popupShown = false;
                }
                else
                    available = true;
            }
            else
                PivotalMessageBox.Show("No stock found for the Product.", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

            return available;
        }

        /// <summary>
        /// Verify the Inventory for the Product.
        /// </summary>
        /// <param name="quantity"></param>
        /// <param name="productId"></param>
        /// <returns></returns>
        private bool InventoryCheckForProduct(int quantity, object productId)
        {
            bool available = false;

            DataTable stockAvailable = Globals.GetDataTable("RE_Inventory for Product? At current Store", new object[] { productId }, "Quantity_Actual");

            if (stockAvailable != null && stockAvailable.Rows.Count > 0 && TypeConvert.ToInt16(stockAvailable.Rows[0]["Quantity_Actual"]) >= 1)
            {
                int totalQty = this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"].AsEnumerable().Where(a => (Id.Create(a["Product_Id"])
                     == Id.Create(productId) && TypeConvert.ToInt32(a["Quantity"]) > 0)).Sum(a => TypeConvert.ToInt32(a["Quantity"]));

                if (quantity > 0 && TypeConvert.ToInt32(stockAvailable.Rows[0]["Quantity_Actual"]) < totalQty)
                    available = false;
                else
                    available = true;
            }

            return available;
        }

        /// <summary>
        /// Show the Authorization screen
        /// </summary>
        /// <param name="showOnlyAuthorization">If true, will show only the Authorization section.</param>
        private void ShowReAuthorizationForm(bool showOnlyAuthorization)
        {
            try
            {
                //Show the Authorization Prompt.
                IActionService actionService = ClientContext.ClientAPIService.GetService<IActionService>();
                IFormActionTarget formActionTarget = actionService.CreateActionTarget<IFormActionTarget>();
                formActionTarget.Form = "RE_Authorization";
                formActionTarget.ParameterList = this.TransitionPointParameter.ParameterList;

                formActionTarget.RecordId = this.RecordId;
                IAction action = actionService.CreateAction(string.Empty, ActionCommand.Show, ActionContent.Record, formActionTarget);
                action.TargetWindow = ActionTargetWindow.Modal;
                var newWindowProp = actionService.CreateNewWindowProperties();
                newWindowProp.UseDefaultSize = false;
                if(showOnlyAuthorization)
                    newWindowProp.Height = 445;
                else
                    newWindowProp.Height = 505;
                newWindowProp.Width = 480;
                action.TargetWindowProperties = newWindowProp;
                actionService.ExecuteAction(action);
                return;
            }
            catch (Exception exc)
            {
                Globals.HandleException(exc, true);
            }
        }
        
        /// <summary>
        /// Check whether the product selected is a valid vousher or not and if not a voucher, then whether it is available for sale or not.
        /// </summary>
        /// <param name="availableForSale">Indicates whether product is available for sale or not</param>
        /// <param name="voucher">True if it is a voucher</param>
        /// <param name="voucherStatus">Status for the voucher selected</param>
        /// <returns></returns>
        private bool ProductAvailableForSale(bool availableForSale, bool voucher, string voucherStatus)
        {
            if (voucher)
            {
                if (string.Equals(voucherStatus, "In Stock"))
                    return true;
                else
                    PivotalMessageBox.Show("Voucher is either Sold or Redeemed.", MessageBoxButtons.OK, MessageBoxIcon.Stop);
            }
            else
            {
                if (availableForSale)
                    return true;
                else
                    PivotalMessageBox.Show("Product is not available for sale.", MessageBoxButtons.OK, MessageBoxIcon.Stop);
            }
            return false;
        }

        /// <summary>
        /// Voids a sale which was done today.
        /// </summary>
        /// <returns>True, if the sale is voided. False otherwise.</returns>
        private bool VoidSale()
        {
            bool success = false;
            if (TypeConvert.ToString(this.PrimaryDataRow["RE_Order_Status"]) == "Processed" && (TypeConvert.ToDateTime(this.PrimaryDataRow["RE_Order_Date"]).Date == DateTime.Now.Date))
            {
                DataTable currentBatch = Globals.GetDataTable("RE_In Progress Batch for Current Store for today?", new object[] { }, "RE_Batch_Id");

                if (currentBatch != null && currentBatch.Rows.Count == 0)
                    PivotalMessageBox.Show("There is no batch currently In Progress.", MessageBoxButtons.OK, MessageBoxIcon.Warning);

                else if (currentBatch != null && currentBatch.Rows.Count == 1)
                {
                    if (Id.Equals(Id.Create(currentBatch.Rows[0]["RE_Batch_Id"]), Id.Create(this.PrimaryDataRow["RE_Batch_Id"])))
                    {
                        if (this.DataSet.Tables["RE_Authorization_Order_Id"].AsEnumerable().Count(a => TypeConvert.ToString(a["Event"]) == "Void Sale.") == 0)
                        {
                            base.NewSecondaryRecord("RE_Authorization_Order_Id");
                            DataTable authorzn = this.FormData.DataSet.Tables["RE_Authorization_Order_Id"];
                            authorzn.Rows[authorzn.Rows.Count - 1]["Authorized"] = DBNull.Value;
                            authorzn.Rows[authorzn.Rows.Count - 1]["RE_Authorized_By_Id"] = DBNull.Value;
                            authorzn.Rows[authorzn.Rows.Count - 1]["Event"] = "Void Sale.";
                        }
                        if (this.FormView.SaveRecord())
                        {
                            //Set the parameter to true as the authorization call is from the Void click.
                            this.TransitionPointParameter.SetUserDefinedParameter(7, true);
                            //Show the Authorization Prompt.
                            this.ShowReAuthorizationForm(false);
                            //Refresh the parent form to reflect the changes.
                            this.LoadRecord();

                            if (this.DataSet.Tables["RE_Authorization_Order_Id"].AsEnumerable().Count(a => TypeConvert.ToBoolean(a["Authorized"]) == true)
                                        == this.DataSet.Tables["RE_Authorization_Order_Id"].Rows.Count)
                            {
                                this.PrimaryDataRow["RE_Order_Status"] = "Void";

                                //Set all the Order product items to Void as the sale status is Void.
                                foreach (DataRow dr in this.FormData.DataSet.Tables["SFA_Order__Product_SFA_Order_I"].Rows)
                                {
                                    dr["RE_Void"] = 1;
                                }

                                this.FormView.SaveRecord();

                                //Update Vouchers.
                                Globals.SystemClient.ExecuteServerTask("RE_Sale", "UpdateVouchers", new Type[] { typeof(DataSet) }, new object[] { this.DataSet });

                                //Adjust the Inventory
                                Globals.SystemClient.ExecuteServerTask("RE_Inventory_Transfer", "processInventory", new Type[] { typeof(string), typeof(string), typeof(object) },
                                                    new object[] { "Void", this.PrimaryDataRow["RE_Type"], TypeConvert.ToDBValue(this.RecordId) });

                                //NN 18092013: Added code to call the CreateAppleCareProduct(which internally calls the "CancelAppleCare" function) for VOID transactions
                                DataTable orderProduct = this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
                                DataRow[] appleCareProducts = orderProduct.AsEnumerable().Where(a => a["RE_RAE_Agreement_Number"] != DBNull.Value).ToArray();
                                //Check if Apple Care Produtcs exists in this Order record.
                                if (appleCareProducts != null && appleCareProducts.Length > 0)
                                {
                                    Globals.SystemClient.ExecuteServerTask("RE_Sale", "CreateAppleCareProduct", new Type[] { typeof(DataSet) }, new object[] { this.DataSet });
                                }
                                success = true;
                            }
                            else
                                PivotalMessageBox.Show("Please authorize the Void transaction.", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                    else
                        PivotalMessageBox.Show("Can not modify the Order as it was created for another Batch.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            return success;
        }

        /// <summary>
        /// Used to calculate the netPrice for Exchange/Refund of Order for Airport counters
        /// If the taxAmount of SourceOrder is 0 then Net Price should be calculated as per current tax percentage,
        /// </summary>
        /// <param name="sourceOrderRow"></param>
        /// <returns></returns>
        /// <history>
        /// #Revision   Date        Author  Description
        /// 6.0.12.0    05/04/2013  NN      Initial Version
        /// </history>
        private double SetPriceForExchangeRefundFromAirportCounter(DataRow sourceOrderRow)
        {
            try
            {                
                double taxPercentage = TypeConvert.ToDouble(Globals.ServerSqlIndex("Employee", "RE_Tax_Rate", SystemClient.UserProfile.EmployeeId));
                double sourceOrderNetPrice = TypeConvert.ToDouble(sourceOrderRow["RE_Extended_Price"]);
                double netPrice = sourceOrderNetPrice - ((sourceOrderNetPrice * taxPercentage) / 100);
                return netPrice;
            }
            catch (Exception exc)
            {
                Globals.HandleException(exc, true);
                return 0;
            }
        }

        /// <summary>
        /// Apply discount for the disocunt condition selected.
        /// </summary>
        /// <param name="isTier1">True, implies it is Tier1 discount condition otherwise Tier2</param>
        /// <param name="orderProduct">SFA Order Product datarow on which the discount is applied.</param>
        /// <history>
        /// Revision   Date        Author  Description
        /// 6.0.9.1    03-12-2011  DS      Initial Version
        /// </history>
        private void ApplyDiscount(bool isTier1, DataRow orderProduct)
        {
            double unitPrice = TypeConvert.ToDouble(orderProduct["Unit_Price"]);
            DataTable authorzn = this.FormData.DataSet.Tables["RE_Authorization_Order_Id"];

            if (!Convert.IsDBNull(isTier1 ? orderProduct["RE_Discount_Condition1_Id"] : orderProduct["RE_Discount_Condition2_Id"]))
            {
                if (unitPrice == 0)
                {
                    PivotalMessageBox.Show("No pricing data found for the Product and the Currency." + Environment.NewLine + "Please contact the Administrator",
                            MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    return;
                }

                DataTable discCondition = Globals.GetDataTable("RE_Discount Conditions For Condition ?", new object[] { isTier1 ? orderProduct["RE_Discount_Condition1_Id"] : 
                    orderProduct["RE_Discount_Condition2_Id"] }, "Amount", "Percent_Value", "Condition_Value_Type", "Apply_To", "Voucher", "Authorization_Needed", "Rn_Descriptor");

                if (discCondition != null && discCondition.Rows.Count > 0)
                {
                    //if Pricing Condition requires a voucher
                    if (isTier1 && TypeConvert.ToBoolean(discCondition.Rows[0]["Voucher"]))
                    {
                        //BR: For Refund, setting the value so that the prompt for Voucher doesn't come once +ve value is entered
                        if ((!isQuantityPositive) && Convert.IsDBNull(orderProduct["RE_Voucher_Number"]))
                            PivotalMessageBox.Show("You have selected Discount which requires a Voucher Number." + Environment.NewLine +
                                "Please enter a Voucher Number corresponding to the row where Voucher? is checked.", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                    if (TypeConvert.ToBoolean(discCondition.Rows[0]["Authorization_Needed"]))
                    {
                        //Delete the Authorization record pushed to Events secondary if chosen earlier.
                        var results = from myRow in authorzn.AsEnumerable()
                                      where myRow.Field<string>("Event") == previousDiscCondDesc
                                      select myRow;
                        if (results.Count() > 0)
                            authorzn.Rows.Remove(results.First());

                        //Create a new Authorization row.
                        base.NewSecondaryRecord("RE_Authorization_Order_Id");
                        authorzn.Rows[authorzn.Rows.Count - 1]["Authorized"] = DBNull.Value;
                        authorzn.Rows[authorzn.Rows.Count - 1]["RE_Authorized_By_Id"] = DBNull.Value;
                        authorzn.Rows[authorzn.Rows.Count - 1]["Event"] = discCondition.Rows[0]["Rn_Descriptor"]; //Discount Condition Name
                    }
                    else
                    {
                        var results = from myRow in authorzn.AsEnumerable()
                                      where myRow.Field<string>("Event") == previousDiscCondDesc
                                      select myRow;
                        if (results.Count() > 0)
                            authorzn.Rows.Remove(results.First());
                    }

                    if (isTier1)
                        orderProduct["RE_Authorization_Needed_1"] = TypeConvert.ToBoolean(discCondition.Rows[0]["Authorization_Needed"]);
                    else
                        orderProduct["RE_Authorization_Needed_2"] = TypeConvert.ToBoolean(discCondition.Rows[0]["Authorization_Needed"]);

                    //Setting the Discount n % values of the particular Discount Type selected for a particular product
                    if (TypeConvert.ToString(discCondition.Rows[0]["Condition_Value_Type"]) == "Amount")
                    {
                        if (isTier1)
                        {
                            //DS:22012013 - Modified for the absolute value
                            orderProduct["Tier1_Discount_Value"] = Math.Abs(TypeConvert.ToDouble(discCondition.Rows[0]["Amount"]) * TypeConvert.ToInt32(orderProduct["Quantity"]));
                            orderProduct["Tier1_Discount_Percent"] = TypeConvert.ToDouble(discCondition.Rows[0]["Amount"]) * 100 / unitPrice;
                        }
                        else
                        {
                            //DS:22012013 - Modified for the absolute value
                            orderProduct["Tier2_Discount_Value"] = Math.Abs(TypeConvert.ToDouble(discCondition.Rows[0]["Amount"]) * TypeConvert.ToInt32(orderProduct["Quantity"]));
                            orderProduct["Tier2_Discount_Percent"] = TypeConvert.ToDouble(discCondition.Rows[0]["Amount"]) * 100 / unitPrice;
                        }
                    }

                    //Setting the % values of the particular Discount Type selected for a particular product
                    if (TypeConvert.ToString(discCondition.Rows[0]["Condition_Value_Type"]) == "Percent")
                    {
                        if (isTier1)
                        {
                            //DS:22012013 - Modified for the absolute value
                            orderProduct["Tier1_Discount_Value"] = Math.Abs((unitPrice * TypeConvert.ToDouble(discCondition.Rows[0]["Percent_Value"]) / 100)
                                * TypeConvert.ToInt32(orderProduct["Quantity"]));
                            orderProduct["Tier1_Discount_Percent"] = TypeConvert.ToDouble(discCondition.Rows[0]["Percent_Value"]);
                        }
                        else
                        {
                            //DS:22012013 - Modified for the absolute value
                            orderProduct["Tier2_Discount_Value"] = Math.Abs((unitPrice * TypeConvert.ToDouble(discCondition.Rows[0]["Percent_Value"]) / 100)
                                * TypeConvert.ToInt32(orderProduct["Quantity"]));
                            orderProduct["Tier2_Discount_Percent"] = TypeConvert.ToDouble(discCondition.Rows[0]["Percent_Value"]);
                        }
                    }
                }
                //Show the values as non-negative
                if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Exchange")
                {
                    if (TypeConvert.ToInt32(orderProduct["Quantity"]) < 0)
                    {
                        orderProduct["Tier1_Discount_Value"] = Math.Abs(TypeConvert.ToDouble(orderProduct["Tier1_Discount_Value"]));
                        //DS: 12052013 - No use of setting this value to 0 when it is NULL. No use of Tier 2 in this specific Implementation.
                        //if (!Convert.IsDBNull(orderProduct["Tier2_Discount_Value"]))
                        //    orderProduct["Tier2_Discount_Value"] = Math.Abs(TypeConvert.ToDouble(orderProduct["Tier2_Discount_Value"]));
                    }
                }
            }
            else
            {
                if (isTier1)
                {
                    orderProduct["Tier1_Discount_Value"] = DBNull.Value;
                    orderProduct["Tier1_Discount_Percent"] = DBNull.Value;
                    orderProduct["RE_Authorization_Needed_1"] = false;
                }
                else
                {
                    orderProduct["Tier2_Discount_Value"] = DBNull.Value;
                    orderProduct["Tier2_Discount_Percent"] = DBNull.Value;
                    orderProduct["RE_Authorization_Needed_2"] = false;
                }

                //Delete the Authorization record pushed to Events secondary as there is no discount condition, hence no authorization required.
                var results = from myRow in authorzn.AsEnumerable()
                              where myRow.Field<string>("Event") == previousDiscCondDesc
                              select myRow;
                if (results.Count() > 0)
                    authorzn.Rows.Remove(results.First());
            }
        }

        /// <summary>
        /// check the quantity against the row where the discount is selected and see if it is less than or equal to the remaining quota.
        /// If the quota exceeds the remaining quota, disallow the discount condition and ask the user to change the discount condition or the quantity.
        /// </summary>
        /// <returns>true, if the verification suceeds.</returns>
        private bool VerifyQuantityForBdayDisc()
        {
            if (!Convert.IsDBNull(this.PrimaryDataRow["Member_Bday_Discount_Id"]) && !Convert.IsDBNull(this.PrimaryDataRow["Bday_Remaining_Quota"]))
            {
                int quantityWithBdayDisc = this.FormData.DataSet.Tables["SFA_Order__Product_SFA_Order_I"].AsEnumerable().Where(a => Id.Create(a["RE_Discount_Condition1_Id"])
                    == Id.Create(this.PrimaryDataRow["Member_Bday_Discount_Id"])).Sum(a => TypeConvert.ToInt32(a["Quantity"]));

                if (quantityWithBdayDisc > TypeConvert.ToInt32(this.PrimaryDataRow["Bday_Remaining_Quota"]))
                {
                    PivotalMessageBox.Show("Total quantity with the Birthday discount exceeds the remaining quota. Either change the discount condition or the quantity.",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// Apply product level discount
        /// </summary>
        /// <param name="productID">Product Id for the line item in the grid.</param>
        /// <param name="orderProduct">Datarow for modification</param>
        /// <param name="rowIndex">Row index in the grid.</param>
        /// <returns></returns>
        private bool ConfigureProductLevelDiscount(object productID, DataRow orderProduct, int rowIndex)
        {
            //If the Product selected has the flag not set "Discount_Applicable". This means there is no discount applicable for this product.
            if (TypeConvert.ToBoolean(orderProduct["Product_Id__RE_Discount_Applic"]))
            {
                DataTable defaultDiscount = Globals.GetDataTable("RE_Discount Condition Tier1 with Product ?",
                    new object[] { productID }, "RE_Discount_Condition_Id");
                if (defaultDiscount != null && defaultDiscount.Rows.Count == 1)
                {
                    orderProduct["RE_Discount_Condition1_Id"] = defaultDiscount.Rows[0]["RE_Discount_Condition_Id"];
                    orderProduct["RE_ProductLevelDisc"] = true;
                    ApplyDiscount(true, orderProduct);

                    if (TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]) != "Top Management")
                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", rowIndex, false);
                    else
                        EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", rowIndex, true);
                    return true;
                }
                else if (defaultDiscount != null && defaultDiscount.Rows.Count > 1)
                {
                    PivotalMessageBox.Show("Could not apply Default Discount for the product as it has multiple default discounts configured." +
                        Environment.NewLine + "Please contact the Administrator.", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return false;
                }
                return false;
            }
            else
            {
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", rowIndex, false);
                return true;
            }
        }

        /// <summary>
        /// Apply member discount
        /// </summary>
        /// <param name="orderProduct"></param>
        private void MemberDiscount(DataRow orderProduct,int rowIndex)
        {
            //NN 21052013: Modified the query to fetch Product->Re_Member_Disc_Condition_Id for Member discounts.
            DataTable memberDiscount = Globals.GetDataTable("RE_Discount Condition for System Member with Product ?",
                new object[] { orderProduct["Product_Id"] }, new string[] { "RE_Discount_Condition_Id", "Rn_Descriptor","Description" });
            if (memberDiscount != null && memberDiscount.Rows.Count > 0)
            {
                orderProduct["RE_Discount_Condition1_Id"] = memberDiscount.Rows[0]["RE_Discount_Condition_Id"];
                orderProduct["RE_Discount_Condition1_Id@Rn_Descriptor"] = memberDiscount.Rows[0]["Rn_Descriptor"];

                //Disabling RE_Discount_Condition1_Id when it set as Member discount
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", rowIndex, false);
                ApplyDiscount(true, orderProduct);
            }
            else
            {
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", rowIndex, true);
            }
        }

        /// <summary>
        /// Set focus on the next secondary cell in case the DC is selected.
        /// </summary>
        /// <param name="Sender"></param>
        /// <param name="args"></param>
        private void SetFocusOnSecondaryCell(DataGridViewColumn Sender, EventArgs args)
        {
            DataGridView dataGridView = Sender.DataGridView;

            dataGridView.Focus();
            dataGridView.CurrentCell = dataGridView[((DataGridViewCellEventArgs)args).ColumnIndex + 1, ((DataGridViewCellEventArgs)args).RowIndex];
            dataGridView.BeginEdit(true);
        }

        /// <summary>
        /// Will be called when an Add Apple Care checkbox is clicked and there is a valid AppleCareProduct applicable for that primary product.
        /// </summary>
        /// <param name="appleCareProductId"></param>
        /// <param name="regDate"></param>
        /// <param name="serialNo"></param>
        /// <param name="purchaseMode"></param>
        /// <history>
        /// #Revision   Date        Author  Description
        /// 6.0.12.0    08/06/2013  NN      Initial Version
        /// </history>
        private void AddAppleCareProductToGrid(Id appleCareProductId, string serialNo, string purchaseMode)
        {
            if (serialNo == string.Empty)
                return;

            DataTable orderProducts = this.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];
            
            DataRow[] appleCareProductAlreadyAdded = orderProducts.AsEnumerable().Where(a => TypeConvert.ToString(a["RE_RAE_Serial_Number"]) == serialNo).ToArray();

            if (appleCareProductAlreadyAdded != null && appleCareProductAlreadyAdded.Length > 0 )
            {
                PivotalMessageBox.Show("The Product is already added with the serial Number " + serialNo + ".", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            object productType = Globals.ServerSqlIndex("Product", "RE_Product_Type", appleCareProductId);

            DataTable price = Globals.GetDataTable("RE_SFA Product Price with Product ? and Currency ? and LOB ?",
            new object[] { appleCareProductId.ToByteArray(), this.PrimaryDataRow["SFA_Currency_Id"], this.PrimaryDataRow["RE_LOB_Id"] }, "Price");           

            if (price != null && price.Rows.Count == 1)
            {
                //Add a record to the secondary
                base.NewSecondaryRecord("SFA_Order__Product_SFA_Order_I");
                

                DataRow newOrderProduct = orderProducts.Rows[orderProducts.Rows.Count - 1];
                int rowIndex = orderProducts.Rows.Count - 1;
                newOrderProduct["Product_Id"] = appleCareProductId.ToByteArray();
                newOrderProduct["RE_Product_Type"] = productType;
                newOrderProduct["RE_Invisible"] = false;                
                newOrderProduct["RE_From_Source_Order"] = false;
                newOrderProduct["Quantity"] = 1;
                newOrderProduct["RE_Item_Scanned"] = true;
                newOrderProduct["RE_RAE_POC_Delivery"] = "E";
                newOrderProduct["RE_RAE_POC_Language"] = "Eng";
                newOrderProduct["RE_RAE_Serial_Number"] = serialNo;
                newOrderProduct["RE_RAE_Agreement_Number"] = null;
                newOrderProduct["RE_RAE_Purchase_Mode"] = purchaseMode;
                newOrderProduct["RE_Original_PO_Number"] = null;               
                
                if (this.PrimaryDataRow["RE_Staff_Code"] != DBNull.Value)
                {
                    newOrderProduct["RE_Staff_Code"] = this.PrimaryDataRow["RE_Staff_Code"];
                    newOrderProduct["RE_Staff_Id"] = this.PrimaryDataRow["RE_Staff_Id"];
                }
                
                newOrderProduct["Unit_Price"] = TypeConvert.ToDouble(price.Rows[0]["Price"]);

                if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) != "Exchange" && TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) != "Refund")
                {
                    if (!ConfigureProductLevelDiscount(appleCareProductId, newOrderProduct, rowIndex))
                    {
                        //Apply Member default discount. If there is no product level discount available, default the discount condition defined 
                        //at the Loyalty program tier of the contact (Member_Discount_Id)
                        if (TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]) == "Member")
                            MemberDiscount(newOrderProduct, rowIndex);
                    }
                }
                else
                {
                    //Added additional chck of Qty < 0,so that it will not apply ExchangeDiscountCondition for New Purchase
                    if (this.PrimaryDataRow["RE_Source_Order_Id"] != DBNull.Value && TypeConvert.ToInt32(newOrderProduct["Quantity"]) < 0)
                    {
                        //This case does not arise here as -ve items can't be added.
                        UpdateExchangeDiscountCondition(Id.Create(this.PrimaryDataRow["RE_Source_Order_Id"]), appleCareProductId, newOrderProduct, rowIndex);
                    }
                    else
                    {
                        if (!ConfigureProductLevelDiscount(appleCareProductId, newOrderProduct, rowIndex))
                        {
                            //Apply Member default discount. If there is no product level discount available, default the discount condition defined 
                            //at the Loyalty program tier of the contact (Member_Discount_Id)
                            if (TypeConvert.ToString(this.PrimaryDataRow["RE_Customer_Type"]) == "Member")
                                MemberDiscount(newOrderProduct, rowIndex);
                        }
                    }

                    if (TypeConvert.ToString(this.PrimaryDataRow["RE_Type"]) == "Exchange")
                    {
                        if (TypeConvert.ToInt32(newOrderProduct["Quantity"]) > 0)
                        {
                            if (!TypeConvert.ToBoolean(newOrderProduct["RE_ProductLevelDisc"]) && TypeConvert.ToBoolean(newOrderProduct["Product_Id__RE_Discount_Applic"]))
                                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_Discount_Condition1_Id", rowIndex, true);
                        }
                    }
                }
                
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "Quantity", rowIndex, false);
                EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_AppleCare_Product", rowIndex, false);

                CommonFieldPopulate(newOrderProduct);
                TotalsSectionCalculations();
            }
            else if (price != null && price.Rows.Count > 1)
                PivotalMessageBox.Show("Multiple pricing defined for the Product and the Currency." + Environment.NewLine + "Please contact the Administrator.",
                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
            else
                PivotalMessageBox.Show("No pricing data found for the Product and the Currency." + Environment.NewLine + "Please contact the Administrator.",
                        MessageBoxButtons.OK, MessageBoxIcon.Stop);
        }        

        /// <summary>
        /// Wil be called user uncheck or delete the Primary Product.
        /// </summary>
        /// <param name="rowIndex"></param>
        /// <history>
        /// #Revision   Date        Author  Description
        /// 6.0.12.0    07/06/2013  NN      Initial Version
        /// </history>
        private int AppleCareProductDeletedOrUnchecked(int rowIndex)
        {
            DataTable orderProduct = this.FormData.DataSet.Tables["SFA_Order__Product_SFA_Order_I"];

            //When Secondary Product Row is getting deleted
            DataRow[] appleCareProductWithSecondarySet = orderProduct.AsEnumerable().Where(a => TypeConvert.ToString(a["RE_RAE_Sec_Serial_No"]) ==
                                            TypeConvert.ToString(orderProduct.Rows[rowIndex]["RE_Product_Serial_No_Id@Rn_Descriptor"])).ToArray();
            if (appleCareProductWithSecondarySet != null && appleCareProductWithSecondarySet.Length > 0)
            {
                appleCareProductWithSecondarySet[0]["RE_RAE_Sec_Serial_No"] = DBNull.Value;
            }
            else
            {
                DataRow[] appleCareProductWithPrimarySet = orderProduct.AsEnumerable().Where(a => TypeConvert.ToString(a["RE_RAE_Serial_Number"]) ==
                                                          TypeConvert.ToString(orderProduct.Rows[rowIndex]["RE_Product_Serial_No_Id@Rn_Descriptor"])).ToArray();
                if (appleCareProductWithPrimarySet != null && appleCareProductWithPrimarySet.Length > 0)
                {
                    if (!Convert.IsDBNull(appleCareProductWithPrimarySet[0]["RE_RAE_Sec_Serial_No"]))
                    {
                        DataRow[] secondaryProducts = orderProduct.AsEnumerable().Where(a => TypeConvert.ToString(a["RE_Product_Serial_No_Id@Rn_Descriptor"]) ==
                                                TypeConvert.ToString(appleCareProductWithPrimarySet[0]["RE_RAE_Sec_Serial_No"])).ToArray();

                        if (secondaryProducts != null && secondaryProducts.Length > 0)
                        {
                            secondaryProducts[0]["RE_AppleCare_Product"] = false;
                            EnableDisableDataGridCell("SFA_Order__Product_SFA_Order_I", "RE_AppleCare_Product", orderProduct.Rows.IndexOf(secondaryProducts[0]), true);
                        }
                    }                    

                    int appleCareRowIndex = orderProduct.Rows.IndexOf(appleCareProductWithPrimarySet[0]);

                    return appleCareRowIndex;
                }
            }

            return 10000;
        }

        #endregion
    }
}
